Week09_어플리케이션 보안
Week 09 · 3과목 어플리케이션 보안
Day 1 · 웹 공격 심화
1-1. 인젝션의 공통 원리
인젝션(Injection)은 "데이터로 들어가야 할 사용자 입력이 코드(명령)의 일부로 해석되는" 모든 취약점의 총칭입니다. 해석기(인터프리터)가 무엇이냐에 따라 이름이 달라질 뿐 원리는 같습니다.
| 해석기 | 공격 이름 | 대표 특수문자 | 근본 대책 |
|---|---|---|---|
| DB(SQL 엔진) | SQL 인젝션 | ' -- ; |
PreparedStatement(바인딩 변수) |
| 브라우저(HTML/JS) | XSS | < > " ' |
출력 인코딩 + CSP |
| OS 셸 | 명령어 삽입 | ; | & ` $() |
셸 호출 금지, 화이트리스트 |
| LDAP 서버 | LDAP 인젝션 | * ( ) | & |
특수문자 이스케이프 |
| XPath 엔진 | XPath 인젝션 | ' or |
파라미터화된 XPath |
| XML 파서 | XXE / XML 삽입 | <!DOCTYPE <!ENTITY |
외부 엔티티(DTD) 비활성화 |
| HTTP 헤더 | HTTP 응답 분할 | \r\n(%0d%0a) |
CR·LF 제거 |
핵심 공식: "입력은 검증하고(Validation), 출력은 그 해석기에 맞게 인코딩하고(Encoding), 코드와 데이터는 분리한다(Parameterization)."
1-2. SQL 인젝션 심화
원리 (단계별)
- 애플리케이션이 사용자 입력을 문자열 연결로 SQL에 붙인다.
- 공격자가
'(문자열 종료)를 넣어 원래 쿼리의 문자열 영역을 탈출한다. - 탈출한 뒤
OR 1=1,UNION SELECT, 주석(--,#) 등을 붙여 쿼리의 논리 자체를 바꾼다. - DB는 바뀐 쿼리를 정상 쿼리로 알고 실행 → 인증 우회, 데이터 유출, 변조, 심하면 OS 명령 실행.
원래 의도: SELECT * FROM users WHERE id='[입력]' AND pw='[입력]'
입력(id): admin' --
실제 실행: SELECT * FROM users WHERE id='admin' --' AND pw='...'
└─ 이후는 주석 → 비밀번호 검사 사라짐
SQL 인젝션 유형
| 유형 | 결과를 얻는 방법 | 특징 / 단서 |
|---|---|---|
| Error-based | DB 오류 메시지에 데이터가 섞여 출력 | 상세 오류 노출이 원인 → 에러처리 취약점과 결합 |
| Union-based | UNION SELECT로 다른 테이블 결과를 같은 화면에 붙여 출력 |
앞 쿼리와 컬럼 수·데이터 타입이 같아야 함 → ORDER BY n으로 컬럼 수 탐색 |
| Blind – Boolean | 화면엔 데이터가 안 나오지만 참/거짓에 따라 응답이 달라짐 | AND 1=1(정상) vs AND 1=2(다름) 비교, 한 글자씩 추측 |
| Blind – Time | 참일 때만 지연시켜 응답 시간으로 판단 | MySQL SLEEP(), MSSQL WAITFOR DELAY, PostgreSQL pg_sleep() |
| Stacked query | ;로 두 번째 쿼리를 이어 붙임 |
DB/드라이버가 다중 쿼리 허용 시 INSERT·DROP 가능 |
| Stored Procedure | 위험한 확장 프로시저 호출 | MSSQL xp_cmdshell → OS 명령 실행. 불필요 프로시저 삭제·비활성화 |
| 2차(Second-order) | 저장된 입력이 나중에 다른 쿼리에서 사용될 때 터짐 | 입력 시점엔 무해해 보여 탐지 어려움 |
| Out-of-band | DNS/HTTP 등 다른 채널로 데이터 유출 | 응답·시간 모두 막혔을 때 |
sequenceDiagram
participant A as 공격자
participant W as 웹앱
participant D as DB
A->>W: id=1 AND 1=1
W->>D: SELECT ... WHERE id=1 AND 1=1
D-->>W: 행 있음
W-->>A: 정상 페이지 (참)
A->>W: id=1 AND 1=2
W->>D: SELECT ... WHERE id=1 AND 1=2
D-->>W: 행 없음
W-->>A: 빈 페이지 (거짓)
Note over A: 응답 차이로 참/거짓을 판별하며
한 글자씩 데이터 추출 (Boolean Blind)취약 코드 vs 안전 코드 (Java/JSP)
// ❌ 취약: 문자열 연결
String id = request.getParameter("id");
String sql = "SELECT * FROM users WHERE id = '" + id + "'";
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery(sql);
// ✅ 안전: PreparedStatement (바인딩 변수)
String sql = "SELECT * FROM users WHERE id = ?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, id); // 입력은 '값'으로만 취급 → 쿼리 구조 불변
ResultSet rs = ps.executeQuery();
- 왜 안전한가? 쿼리 구조가 먼저 컴파일되고, 입력값은 나중에 데이터 자리에만 들어가므로
'가 들어와도 문자열 종료 기호가 아니라 그냥 글자'로 취급됩니다. - 주의:
ORDER BY·테이블명·컬럼명은 바인딩 변수로 넣을 수 없음 → **허용 목록(화이트리스트)**에서 골라 쓰기. - MyBatis:
#{}는 바인딩(안전),${}는 문자열 치환(취약).
// PHP – PDO 사용
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
$stmt->execute([':id' => $_GET['id']]);
SQL 인젝션 대응 정리
- PreparedStatement / 파라미터화 쿼리 (1순위)
- 입력값 검증: 타입·길이·형식 체크, 특수문자 필터링(보조 수단)
- DB 계정 최소 권한: 웹 앱 계정에 DROP·관리자 권한 X,
xp_cmdshell등 비활성화 - 상세 오류 메시지 숨김 (Error-based 차단)
- 저장 프로시저 사용 시에도 내부에서 동적 SQL 문자열 연결하면 여전히 취약
- WAF로 탐지·차단(보조)
1-3. XSS (Cross-Site Scripting)
원리
XSS는 공격자의 스크립트가 피해자의 브라우저에서, 취약한 사이트의 출처(Origin) 권한으로 실행되는 공격입니다. 브라우저는 같은 출처의 스크립트를 믿기 때문에, 그 스크립트는 해당 사이트의 쿠키(HttpOnly가 아니면)·DOM·사용자 권한에 접근할 수 있습니다.
- 피해: 세션 쿠키 탈취 → 세션 하이재킹, 화면 변조(피싱 폼 삽입), 키로깅, 악성 사이트 리다이렉트, 사용자 권한으로 요청 전송
- 공격 대상: 서버가 아니라 다른 사용자(클라이언트)
3가지 유형 흐름
① Stored(저장형) — 서버에 저장된 뒤 열람하는 모든 사람에게 실행
sequenceDiagram
participant A as 공격자
participant S as 웹서버(게시판)
participant V as 피해자
A->>S: 게시글 등록 (본문에 스크립트 포함)
S->>S: DB에 그대로 저장
V->>S: 게시글 열람
S-->>V: 스크립트가 포함된 HTML 응답
V->>V: 브라우저가 스크립트 실행
V->>A: 쿠키·정보 전송② Reflected(반사형) — 악성 링크의 파라미터가 응답에 반사
sequenceDiagram
participant A as 공격자
participant V as 피해자
participant S as 웹서버(검색)
A->>V: 악성 링크 전달 (메일·메신저)
V->>S: GET /search?q=스크립트
S-->>V: "검색어: 스크립트" 그대로 출력
V->>V: 브라우저가 스크립트 실행
V->>A: 쿠키·정보 전송③ DOM 기반 — 서버 응답은 정상, 클라이언트 JS가 URL 등을 DOM에 넣다가 실행
sequenceDiagram
participant A as 공격자
participant V as 피해자 브라우저
participant S as 웹서버
A->>V: 악성 링크 (page.html#스크립트)
V->>S: GET /page.html (# 뒤는 서버로 안 감)
S-->>V: 정상 HTML + JS
V->>V: JS가 location.hash를 innerHTML에 삽입
V->>V: 스크립트 실행| 구분 | Stored | Reflected | DOM 기반 |
|---|---|---|---|
| 악성 코드 위치 | 서버 DB/파일 | 요청 파라미터 | URL 조각·클라이언트 데이터 |
| 서버 응답에 포함? | O | O | X (서버 로그에도 안 남을 수 있음) |
| 피해자 행동 | 게시글 열람만 | 링크 클릭 | 링크 클릭 |
| 피해 범위 | 가장 넓음 | 클릭한 사람 | 클릭한 사람 |
| 핵심 대책 | 출력 인코딩 | 출력 인코딩 | 안전한 DOM API (textContent), innerHTML·eval·document.write 금지 |
취약 코드 vs 안전 코드
<%-- ❌ 취약: 입력을 그대로 출력 --%>
검색어: <%= request.getParameter("q") %>
<%-- ✅ 안전: JSTL c:out은 기본적으로 HTML 이스케이프 --%>
검색어: <c:out value="${param.q}" />
// ❌ 취약
echo "검색어: " . $_GET['q'];
// ✅ 안전: HTML 엔티티 인코딩
echo "검색어: " . htmlspecialchars($_GET['q'], ENT_QUOTES, 'UTF-8');
// ❌ DOM XSS
document.getElementById("msg").innerHTML = location.hash.substring(1);
// ✅ 텍스트로만 삽입
document.getElementById("msg").textContent = location.hash.substring(1);
HTML 엔티티 변환표 (시험 단골):
| 문자 | 엔티티 |
|---|---|
< |
< |
> |
> |
" |
" |
' |
' |
& |
& |
/ |
/ (권고) |
- 출력 위치(컨텍스트)별 인코딩이 다름: HTML 본문 / HTML 속성 / JavaScript 문자열 / URL 파라미터 / CSS → 각각 다른 인코딩 필요.
- 게시판에서 HTML을 허용해야 하면: 허용 태그 화이트리스트 기반 HTML 정화(Sanitizer) 라이브러리 사용 (블랙리스트는 우회 쉬움 — 대소문자 혼합,
<img onerror>등).
CSP (Content Security Policy)
응답 헤더로 **"이 페이지에서 실행·로딩 가능한 출처"**를 브라우저에 알려 주는 심층 방어 수단입니다. 인코딩을 놓쳐도 인라인 스크립트·외부 스크립트 로딩을 막아 피해를 줄입니다.
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-r4nd0m'; object-src 'none'; frame-ancestors 'none'; report-uri /csp-report
| 지시어 | 의미 |
|---|---|
default-src 'self' |
기본적으로 같은 출처만 허용 |
script-src 'self' 'nonce-…' |
같은 출처 + 해당 nonce가 붙은 스크립트만 실행 (인라인 스크립트 차단) |
object-src 'none' |
플러그인(Flash 등) 차단 |
frame-ancestors 'none' |
다른 사이트가 iframe으로 감싸지 못함 → 클릭재킹 방어 (X-Frame-Options 대체) |
report-uri |
위반 보고 |
'unsafe-inline','unsafe-eval'을 넣으면 XSS 방어 효과가 크게 약해짐.- 쿠키 HttpOnly: JS(
document.cookie)로 쿠키 접근 차단 → XSS가 있어도 세션 쿠키 탈취만은 어렵게 함. (XSS 자체를 막는 것은 아님!)
1-4. CSRF (Cross-Site Request Forgery)
원리
- 피해자가 은행 사이트에 로그인된 상태(세션 쿠키 보유)다.
- 피해자가 공격자 페이지(또는 악성 게시글)를 연다.
- 그 페이지가 은행으로 요청을 자동 전송하게 만든다(
<img>, 자동 submit form). - 브라우저는 은행 도메인 요청이므로 쿠키를 자동으로 첨부한다.
- 은행 서버는 "정상 로그인 사용자의 요청"으로 판단 → 송금·비밀번호 변경 실행.
sequenceDiagram
participant V as 피해자 브라우저
participant B as 은행 서버
participant E as 공격자 사이트
V->>B: 로그인
B-->>V: 세션 쿠키 발급
V->>E: 공격자 페이지 방문
E-->>V: 자동 전송 폼 (송금 요청) 포함 HTML
V->>B: POST /transfer (쿠키 자동 첨부)
B->>B: 세션 유효 → 송금 처리
Note over B: 서버는 사용자가 의도했는지 구분 불가| 구분 | XSS | CSRF |
|---|---|---|
| 악성 코드 실행 위치 | 피해자 브라우저(취약 사이트 출처로) | 피해자 브라우저가 요청만 보냄 |
| 공격자가 노리는 것 | 클라이언트(쿠키·화면·정보) | 서버에 사용자 권한의 행위를 시킴 |
| 응답을 공격자가 읽나 | 읽을 수 있음 | 보통 못 읽음(요청만 위조) |
| 신뢰 관계 악용 | 사용자가 사이트를 신뢰 | 사이트가 사용자 브라우저를 신뢰 |
| 대표 대책 | 출력 인코딩, CSP, HttpOnly | CSRF 토큰, SameSite, 재인증 |
CSRF 토큰 구현 예 (JSP)
<%-- 폼 생성 시: 세션에 토큰 저장 후 hidden 필드로 출력 --%>
<%
String token = java.util.UUID.randomUUID().toString(); // 예측 불가 값
session.setAttribute("csrfToken", token);
%>
<form method="POST" action="/transfer">
<input type="hidden" name="csrfToken" value="<%= token %>">
...
</form>
// 요청 처리 시: 세션 토큰과 요청 토큰 비교
String sent = request.getParameter("csrfToken");
String saved = (String) session.getAttribute("csrfToken");
if (saved == null || !saved.equals(sent)) {
response.sendError(403); // 위조 요청 차단
return;
}
- 공격자는 피해자 세션의 토큰 값을 모르므로 유효한 요청을 만들 수 없음.
- 단, XSS가 있으면 CSRF 토큰도 읽혀서 무력화됨 → XSS 먼저 막아야 함.
- 기타 대책: SameSite 쿠키(
Strict/Lax: 다른 사이트에서 시작된 요청에 쿠키 미첨부), 중요 기능 재인증·추가 인증, Referer/Origin 검증(보조), 상태 변경은 GET 금지·POST만, CAPTCHA.
1-5. 파일 업로드 · 웹셸
sequenceDiagram
participant A as 공격자
participant W as 웹서버
A->>W: 이미지 업로드 폼에 shell.jsp 업로드
W->>W: 확장자 검사 없음 → /upload/shell.jsp 저장
A->>W: GET /upload/shell.jsp?cmd=...
W->>W: 웹 루트 안이고 실행 권한 있음 → JSP로 실행
W-->>A: OS 명령 실행 결과 반환
Note over A,W: 서버 장악, 내부망 이동 거점우회 기법(알아 두면 함정 대비): shell.php.jpg(이중 확장자), shell.pHp(대소문자), Content-Type: image/jpeg 위조, shell.php%00.jpg(널바이트, 구형 환경), .htaccess 업로드로 jpg를 PHP로 해석시키기.
// ✅ 업로드 검증 예
String name = file.getOriginalFilename();
String ext = name.substring(name.lastIndexOf('.') + 1).toLowerCase();
Set<String> allow = Set.of("jpg", "png", "gif", "pdf");
if (!allow.contains(ext)) throw new SecurityException("허용되지 않은 확장자");
if (file.getSize() > 5 * 1024 * 1024) throw new SecurityException("크기 초과");
String saveName = UUID.randomUUID() + "." + ext; // 파일명 랜덤화
Path dest = Paths.get("/data/upload_store", saveName); // 웹 루트 밖 저장
file.transferTo(dest.toFile());
| 대책 | 이유 |
|---|---|
| 확장자 화이트리스트 (서버 측) | 블랙리스트는 .phtml, .jspx 등 우회 |
| MIME·매직넘버(파일 시그니처) 확인 | Content-Type 헤더는 위조 가능 → 보조 |
| 저장 파일명 랜덤화 | 공격자가 경로를 추측 못 함 |
| 웹 루트 밖 저장, 다운로드는 별도 스크립트 | URL로 직접 실행 불가 |
| 업로드 디렉터리 실행 권한 제거 | Apache php_admin_flag engine off, RemoveHandler 등 |
| 크기 제한 | DoS 방지 (LimitRequestBody) |
- 웹셸 탐지: 웹 디렉터리 무결성 검사(파일 생성/변경 모니터링), 웹셸 탐지 도구, 로그에서 업로드 디렉터리의
.jsp/.php호출·cmd=파라미터 확인.
1-6. 경로 조작 · 파일 다운로드
download.jsp?file=../../../../etc/passwd 처럼 ../로 상위 디렉터리로 이동해 허용되지 않은 파일을 읽는 공격. 인코딩 우회(%2e%2e%2f, ..%2f, ....//)가 흔함.
// ❌ 취약
File f = new File("/data/files/" + request.getParameter("file"));
// ✅ 안전: 정규화 후 기준 디렉터리 안인지 확인
Path base = Paths.get("/data/files").toRealPath();
Path target = base.resolve(request.getParameter("file")).normalize();
if (!target.startsWith(base)) {
throw new SecurityException("경로 조작 시도");
}
- 더 좋은 방법: 파일명을 직접 받지 말고 **파일 ID(번호)**를 받아 서버가 DB에서 실제 경로를 조회.
1-7. 기타 서버 측 공격
SSRF (Server-Side Request Forgery)
서버가 사용자가 준 URL로 대신 요청하는 기능(URL 미리보기, 이미지 가져오기, 웹훅)을 악용해 외부에서 직접 닿을 수 없는 내부 자원에 접근.
sequenceDiagram
participant A as 공격자
participant W as 웹서버(클라우드)
participant M as 메타데이터 169.254.169.254
A->>W: POST /preview url=http://169.254.169.254/latest/meta-data/...
W->>M: 서버가 내부에서 요청
M-->>W: 임시 자격증명(Access Key)
W-->>A: 미리보기 결과로 그대로 노출
Note over A: 클라우드 계정 권한 탈취- 대상: 클라우드 메타데이터(
169.254.169.254),localhost관리 페이지, 내부망 IP,file://스킴 - 대응: 허용 도메인 화이트리스트, 사설·루프백·링크로컬 IP 차단(DNS 해석 후 검사, 리다이렉트 따라가지 않기), 허용 스킴 http/https만, 응답 그대로 반환 금지, 클라우드 IMDSv2(토큰 필요) 사용
XXE (XML External Entity)
<?xml version="1.0"?>
<!DOCTYPE data [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<data>&xxe;</data>
- XML 파서가 외부 엔티티를 해석해 서버 파일 읽기, SSRF, DoS(Billion Laughs: 엔티티 중첩 폭증) 발생
- 대응: DTD·외부 엔티티 처리 비활성화 (Java:
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true)), JSON 등 단순 포맷 사용
OS 명령어 삽입
// ❌ 취약: ping 기능
system("ping -c 1 " . $_GET['ip']); // ip=127.0.0.1; cat /etc/passwd
// ✅ 개선: 형식 검증 + 인자 이스케이프 (가능하면 셸 호출 자체를 피함)
if (!filter_var($_GET['ip'], FILTER_VALIDATE_IP)) exit("invalid");
system("ping -c 1 " . escapeshellarg($_GET['ip']));
- 셸 메타문자:
;&&&|||`$()>\n - 대응: 시스템 명령 호출 대신 언어 내장 API, 불가피하면 허용값 화이트리스트, 웹 서버 계정 최소 권한
오픈 리다이렉트 (신뢰되지 않는 URL로 자동 접속)
/login?next=http://evil.example → 로그인 후 피싱 사이트로 이동. 정상 도메인 링크라 사용자가 의심 안 함.
- 대응: 리다이렉트 대상 화이트리스트 또는 상대경로만 허용, 외부 이동 시 경고 페이지
HTTP 응답 분할 (Response Splitting)
입력값이 응답 헤더(Location, Set-Cookie)에 들어갈 때 %0d%0a(CRLF)를 넣어 헤더를 끊고 가짜 헤더·본문을 추가.
요청: /redirect?lang=ko%0d%0aSet-Cookie:%20admin=true
응답: Location: /home?lang=ko
Set-Cookie: admin=true ← 공격자가 만든 헤더
- 대응: 헤더에 들어가는 값에서 CR(
\r)·LF(\n) 제거. (최신 WAS는 기본 차단하는 경우 많음)
LDAP / XPath 인젝션
- LDAP:
(&(uid=입력)(pw=입력))에*)(uid=*))(|(uid=*같은 입력 → 필터 논리 변경, 인증 우회. 대응:* ( ) \ NUL이스케이프 - XPath: XML 기반 인증에서
' or '1'='1→ 전체 노드 반환. 대응: 파라미터화 XPath, 입력 검증
안전하지 않은 역직렬화 (Insecure Deserialization)
직렬화된 객체(Java ObjectInputStream, PHP unserialize)를 신뢰할 수 없는 입력에서 복원할 때, 복원 과정에서 호출되는 메서드 체인(가젯 체인)이 원격 코드 실행으로 이어질 수 있음.
- 대응: 신뢰할 수 없는 데이터 역직렬화 금지, JSON 등 데이터 전용 포맷, 허용 클래스 화이트리스트, 무결성 서명 검증
- 시큐어코딩 분류: 코드오류(신뢰할 수 없는 데이터의 역직렬화) / OWASP 2021: A08 무결성 실패
1-8. 인증 · 세션 관리 취약점
| 취약점 | 내용 | 대응 |
|---|---|---|
| 무차별 대입 / 크리덴셜 스터핑 | 비밀번호 반복 시도, 유출 계정 재사용 | 로그인 실패 횟수 제한, CAPTCHA, MFA |
| 취약한 비밀번호 허용 | 1234 허용 |
복잡도·길이 정책 |
| 세션 고정(Fixation) | 공격자가 미리 정한 세션 ID를 피해자가 그대로 로그인에 사용 | 로그인 성공 시 세션 ID 재발급 |
| 세션 하이재킹 | 쿠키 탈취(XSS, 스니핑) | HttpOnly, Secure(HTTPS 전용), 짧은 만료, IP/UA 바인딩(보조) |
| 예측 가능한 세션 ID | 순차 번호 | 충분히 긴 암호학적 난수 |
| URL에 세션 ID 노출 | ;jsessionid=... → Referer·로그로 유출 |
쿠키로만 전달 |
| 로그아웃 미흡 | 서버 세션이 남아 있음 | 서버 측 세션 무효화(session.invalidate()) |
| 불충분한 인가 | URL 직접 입력으로 관리자 기능 | 모든 요청에 서버 측 권한 검사 |
| 쿠키 변조 | role=user → role=admin |
권한 정보는 서버 세션에, 쿠키는 서명/암호화 |
| 정보 노출 | 오류 메시지, 주석, 백업 파일(.bak) |
공통 에러 페이지, 배포 전 정리 |
쿠키 속성:
| 속성 | 효과 |
|---|---|
HttpOnly |
JS에서 쿠키 접근 불가 (XSS로 인한 쿠키 탈취 완화) |
Secure |
HTTPS에서만 전송 (스니핑 방지) |
SameSite=Strict |
다른 사이트에서 시작된 요청엔 쿠키 전송 안 함 |
SameSite=Lax |
최상위 GET 이동만 허용 (최신 브라우저 기본값) |
SameSite=None |
항상 전송, 반드시 Secure와 함께 |
- HttpOnly는 XSS를 "막는" 대책이 아니라 쿠키 탈취 "피해를 줄이는" 대책. "XSS 근본 대책 = HttpOnly"는 틀림 → 근본은 출력 인코딩.
- CSRF 토큰은 XSS가 있으면 무력화된다. 반대로 CSRF 대책은 XSS를 막지 못한다.
- DOM XSS는 서버를 거치지 않을 수 있어 서버 측 필터·로그로 못 잡는 경우가 있다.
- PreparedStatement를 써도
ORDER BY·테이블명을 문자열로 붙이면 여전히 취약. MyBatis${}는 취약,#{}는 안전. - Blind SQLi는 "결과가 화면에 안 나와도" 가능하다 → 오류 메시지를 숨겼다고 SQLi가 해결된 것 아님.
- SSRF는 서버가 요청을 보내고, CSRF는 피해자 브라우저가 요청을 보낸다. 이름이 비슷해 단골 함정.
- 파일 업로드에서 Content-Type 검사만으로는 부족(위조 가능), 클라이언트 측(JS) 검사만으로도 부족.
- XSS 유형 3가지를 시나리오로 주고 어느 유형인지 고르게 하는 문제가 자주 나옴 (게시판 저장 → Stored, 링크 파라미터 → Reflected,
#뒤 값·클라이언트 JS → DOM). - SQLi 유형 구분: 응답 시간 차이 → Time-based Blind, 참/거짓 응답 차이 → Boolean Blind,
UNION으로 컬럼 수 맞추기 → Union-based,xp_cmdshell→ 저장 프로시저 악용. - CSRF의 정의(사용자 의도와 무관한 요청을 인증된 사용자 권한으로 전송)와 대표 대책(토큰·재인증·SameSite).
- 파일 업로드 대책 항목 고르기: 화이트리스트, 실행권한 제거, 웹 루트 밖 저장, 파일명 변경.
- HTML 엔티티 변환(
<→<)을 주관식으로 쓰게 하는 형태.
확인 문제 (Day 1)
Q1. 게시판 글 본문에 포함된 스크립트가 DB에 저장되어, 그 글을 열람하는 모든 사용자의 브라우저에서 실행되었다. 이 공격 유형은?
① Reflected XSS ② Stored XSS ③ DOM 기반 XSS ④ CSRF
정답: ②
- ① 틀림: 반사형은 요청 파라미터가 그 응답에 즉시 반사되며 저장되지 않음.
- ② 맞음: 서버에 저장되어 열람자마다 실행 → 저장형.
- ③ 틀림: DOM 기반은 클라이언트 JS가 URL 조각 등을 DOM에 넣는 과정에서 발생.
- ④ 틀림: CSRF는 스크립트 실행이 아니라 사용자 권한으로 요청을 위조하는 것.
Q2. 웹 페이지가 데이터를 출력하지 않지만, 입력 조건이 참일 때만 응답이 5초 늦어지는 현상을 이용해 DB 정보를 추출했다. 해당 기법은?
① Union-based SQL Injection ② Error-based SQL Injection ③ Time-based Blind SQL Injection ④ Stacked Query
정답: ③
- ① 틀림: 결과를 화면에 붙여서 보는 방식.
- ② 틀림: 오류 메시지에 데이터가 노출되는 방식.
- ③ 맞음: 응답 지연 시간으로 참/거짓을 판단.
- ④ 틀림:
;로 추가 쿼리를 실행하는 방식이며 시간 측정이 핵심이 아님.
Q3. 다음 중 CSRF 대응책으로 가장 거리가 먼 것은?
① 요청마다 예측 불가능한 토큰을 폼에 포함하여 서버에서 검증 ② 세션 쿠키에 SameSite=Strict 속성 부여 ③ 송금 등 중요 기능 실행 시 비밀번호 재입력 ④ 출력 시 <를 <로 변환
정답: ④
- ①②③ 모두 CSRF 대책(토큰, 교차 사이트 요청 시 쿠키 미전송, 재인증).
- ④ 틀림(정답): HTML 엔티티 인코딩은 XSS 대책. CSRF는 스크립트 실행 없이 요청만 위조하므로 직접 대책이 아님.
Q4. 이미지 미리보기 기능에 http://169.254.169.254/...를 입력해 서버가 클라우드 메타데이터에서 자격증명을 가져와 응답에 노출했다. 이 취약점과 대책의 연결로 옳은 것은?
① CSRF – CSRF 토큰 ② SSRF – 요청 대상 화이트리스트 및 내부 IP 차단 ③ XXE – DTD 비활성화 ④ Open Redirect – 상대 경로만 허용
정답: ②
- ① 틀림: 요청 주체가 피해자 브라우저가 아니라 서버.
- ② 맞음: 서버가 공격자 지정 URL로 요청 → SSRF. 화이트리스트·사설/링크로컬 IP 차단·IMDSv2.
- ③ 틀림: XML 엔티티를 이용한 것이 아님.
- ④ 틀림: 사용자를 다른 사이트로 이동시키는 공격이 아님.
Q5. 파일 업로드 취약점 대응으로 적절하지 않은 것은?
① 업로드 파일을 웹 루트 바깥 디렉터리에 저장한다 ② 허용할 확장자만 서버 측에서 검사한다 ③ 클라이언트 JavaScript에서 확장자를 검사하고 서버에서는 검사하지 않는다 ④ 업로드 디렉터리의 스크립트 실행 권한을 제거한다
정답: ③
- ①②④ 모두 올바른 대책.
- ③ 틀림(정답): 클라이언트 검사는 프록시 도구로 쉽게 우회. 반드시 서버 측 검증.
Q6. 로그인 전 공격자가 발급받은 세션 ID를 피해자가 사용하게 만든 뒤, 피해자가 로그인하면 같은 세션 ID로 접근하는 공격과 그 대책은?
① 세션 하이재킹 – HttpOnly ② 세션 고정 – 로그인 성공 시 세션 ID 재발급 ③ CSRF – Referer 검증 ④ 크리덴셜 스터핑 – 계정 잠금
정답: ②
- ① 틀림: 하이재킹은 이미 쓰고 있는 세션 ID를 탈취하는 것.
- ② 맞음: 미리 고정해 둔 세션 ID를 쓰게 하는 것이 세션 고정. 로그인 후 새 ID를 발급하면 공격자의 ID는 무효.
- ③④ 틀림: 다른 공격.
Day 2 · OWASP Top 10 · 웹 서버 보안 설정 · WAF · 로그 분석
2-1. OWASP Top 10 (2021) 항목별 이해
OWASP(Open Web Application Security Project)는 웹 애플리케이션 보안 위험을 약 3~4년 주기로 순위화합니다. 시험은 2021판 기준 문제가 많으므로 2021판을 완벽히, 2025판은 변경점만 알아 두세요.
| 순위 | 항목 | 쉬운 설명 | 예시 | 대표 대책 |
|---|---|---|---|---|
| A01 | 취약한 접근 통제 (Broken Access Control) | 권한 없는 기능·데이터에 접근 | URL의 id=123을 124로 바꿔 남의 주문 조회(IDOR), 일반 사용자가 /admin 접근 |
서버 측 기본 거부(deny by default), 객체 소유자 확인 |
| A02 | 암호화 실패 (Cryptographic Failures) | 민감정보를 암호화 안 하거나 약하게 함 (옛 "민감 데이터 노출") | HTTP 평문 전송, MD5로 비밀번호 저장, 하드코딩된 키 | TLS, 솔트+느린 해시(bcrypt, PBKDF2, Argon2), 강한 알고리즘 |
| A03 | 인젝션 (Injection) | SQL·OS·LDAP 인젝션, XSS도 여기 포함(2021부터) | ' OR '1'='1 |
파라미터화 쿼리, 출력 인코딩 |
| A04 | 안전하지 않은 설계 (Insecure Design) — 신규 | 구현 실수가 아니라 설계 자체의 결함 | 비밀번호 찾기 질문이 "좋아하는 색", 예약 수량 제한 없음 | 위협 모델링, 보안 설계 패턴, 오용 사례 |
| A05 | 보안 설정 오류 (Security Misconfiguration) | 기본 계정·불필요 기능·상세 오류 노출 (XXE 포함) | 디렉터리 리스팅, 기본 관리자 비밀번호, 샘플 앱 방치 | 하드닝 표준, 자동화된 설정 점검 |
| A06 | 취약하고 오래된 구성요소 | 패치 안 된 라이브러리·프레임워크 | 취약한 Log4j, 구버전 Struts | SCA 도구, 구성요소 목록(SBOM), 패치 |
| A07 | 식별 및 인증 실패 | 인증·세션 관리 결함 (옛 "취약한 인증") | 무차별 대입 허용, 세션 고정, 약한 비밀번호 | MFA, 시도 제한, 세션 재발급 |
| A08 | 소프트웨어 및 데이터 무결성 실패 — 신규 | 무결성 검증 없는 업데이트·CI/CD·역직렬화 | 서명 없는 자동 업데이트, 신뢰할 수 없는 CDN 스크립트 | 전자서명 검증, SRI, 파이프라인 보안 |
| A09 | 보안 로깅 및 모니터링 실패 | 공격을 탐지·대응 못 함 | 로그인 실패를 기록 안 함, 경보 없음 | 감사 로그, 중앙 수집, 경보 |
| A10 | SSRF — 신규 | 서버가 공격자 지정 URL로 요청 | 메타데이터 탈취 | URL 화이트리스트, 내부망 분리 |
2017 → 2021 주요 변화 (암기용)
- 2017 A5 취약한 접근 통제가 2021 1위로 상승
- 2017 A7 XSS가 인젝션(A03)에 통합
- 2017 A4 XXE가 보안 설정 오류(A05)에 통합
- 2017 A8 안전하지 않은 역직렬화가 무결성 실패(A08)에 통합
- 신규 3개: 안전하지 않은 설계, 무결성 실패, SSRF
A01 취약한 접근 통제(SSRF가 여기에 흡수) / A02 보안 설정 오류(5위→2위) / A03 소프트웨어 공급망 실패(신규, 2021 A06 확장) / A04 암호화 실패 / A05 인젝션 / A06 안전하지 않은 설계 / A07 인증 실패 / A08 소프트웨어·데이터 무결성 실패 / A09 보안 로깅 및 경보 실패 / A10 예외 상황의 부적절한 처리(신규).
시험 문제가 몇 년판을 기준으로 하는지 지문을 꼭 확인할 것. 연도 언급이 없으면 2021판 기준으로 생각하되 보기와 대조.
2-2. 웹 서버 보안 설정 (하드닝)
Apache httpd.conf 예시와 해설
# 1) 실행 계정: root가 아닌 전용 계정
User apache
Group apache
# 2) 버전 정보 숨김
ServerTokens Prod # 응답 헤더 Server: Apache (버전·OS 숨김)
ServerSignature Off # 오류 페이지 하단 서버 정보 숨김
# 3) 루트 디렉터리는 기본 거부
<Directory />
Options None
AllowOverride None
Require all denied
</Directory>
# 4) 웹 문서 디렉터리
<Directory "/var/www/html">
Options -Indexes -FollowSymLinks -ExecCGI # 리스팅·심볼릭링크·CGI 실행 금지
AllowOverride None # .htaccess 무시
Require all granted
<LimitExcept GET POST> # GET/POST 외 메서드 차단
Require all denied
</LimitExcept>
</Directory>
# 5) 업로드 디렉터리에서 스크립트 실행 금지
<Directory "/var/www/html/upload">
php_admin_flag engine off
RemoveHandler .php .phtml
</Directory>
# 6) 기타
TraceEnable Off # TRACE 메서드 비활성화 (XST 방지)
LimitRequestBody 5242880 # 요청 본문 5MB 제한
Timeout 60 # Slowloris 등 완화
ErrorDocument 404 /error.html
ErrorDocument 500 /error.html
| 설정 | 하는 일 | 막는 위협 |
|---|---|---|
Options -Indexes |
index 파일 없을 때 파일 목록 표시 금지 | 디렉터리 리스팅 정보 노출 |
Options -FollowSymLinks |
심볼릭 링크 따라가기 금지 | /etc 등으로의 링크를 통한 파일 노출 |
ServerTokens Prod |
Server 헤더를 최소화 | 버전 기반 공격 정보 수집 |
ServerSignature Off |
오류 페이지 서명 제거 | 정보 노출 |
AllowOverride None |
.htaccess 무시 |
업로드된 .htaccess로 설정 변경 |
<LimitExcept GET POST> |
그 외 메서드 거부 | PUT/DELETE 악용 |
TraceEnable Off |
TRACE 차단 | XST(Cross-Site Tracing, HttpOnly 쿠키 우회) |
LimitRequestBody |
본문 크기 제한 | 대용량 업로드 DoS |
User/Group |
비특권 계정 실행 | 침해 시 피해 범위 최소화 |
ErrorDocument |
공통 오류 페이지 | 스택 트레이스·경로 노출 |
- Apache 로그:
access_log(요청),error_log(오류). 설정 지시어CustomLog,ErrorLog,LogFormat. - 불필요 파일 삭제:
manual, 샘플·테스트 페이지,cgi-bin의 예제 스크립트, 백업 파일(.bak,.old). - 응답 보안 헤더(보조):
X-Content-Type-Options: nosniff,Strict-Transport-Security(HSTS, HTTPS 강제),X-Frame-Options: DENY(클릭재킹),Content-Security-Policy.
IIS · Tomcat 기본
| 서버 | 보안 설정 포인트 |
|---|---|
| IIS | 디렉터리 검색(Directory Browsing) 비활성화, 불필요한 ISAPI/CGI·WebDAV 제거, 요청 필터링(확장자·동사·길이), X-Powered-By 등 헤더 제거, 상세 오류 → 사용자 지정 오류, 앱 풀을 저권한 ID로, 샘플·기본 사이트 삭제 |
| Tomcat | manager/host-manager 앱 삭제 또는 IP 제한, tomcat-users.xml 기본 계정·비밀번호 제거, shutdown 포트(8005) 비활성화 또는 명령 문자열 변경, web.xml의 DefaultServlet listings=false, server.xml Connector의 server 속성으로 버전 숨김, examples·docs 앱 삭제, 오류 페이지 설정 |
2-3. WAF (웹 방화벽)
왜 필요한가
일반 방화벽·IPS는 주로 IP·포트·패킷 수준을 봅니다. 웹 공격은 정상 포트(80/443)로, 정상 HTTP 형식 안에 들어오므로 **HTTP 요청·응답 내용(파라미터, 헤더, 본문)**을 이해하는 전용 장비가 필요합니다. HTTPS는 WAF에서 SSL/TLS를 복호화(서버 인증서·키 탑재)해야 검사할 수 있습니다.
| 구분 | 종류 | 설명 |
|---|---|---|
| 탐지 모델 | 네거티브(블랙리스트) | 알려진 공격 시그니처와 일치하면 차단. 구축 쉬움, 신규 공격에 약함 |
| 포지티브(화이트리스트) | 허용된 정상 패턴만 통과. 정교하지만 학습·튜닝 필요, 오탐 위험 | |
| 운영 모드 | 탐지(모니터링) 모드 | 기록만 하고 차단 X → 초기 도입 시 오탐 확인 |
| 차단 모드 | 정책 위반 시 차단 | |
| 학습 모드 | 정상 트래픽을 학습해 포지티브 정책 생성 | |
| 배치 | 네트워크 기반(리버스 프록시/인라인/투명 브리지) | 앞단 장비로 여러 서버 보호 |
| 호스트 기반 | 웹 서버 모듈(ModSecurity) 형태 | |
| 클라우드 기반 | DNS를 WAF 서비스로 돌려 경유 |
- WAF가 하는 일: SQLi·XSS 차단, 파일 업로드 검사, 응답의 개인정보·오류 메시지 유출 차단(응답 검사), 쿠키 변조 방지, 접근 제어.
- 대표: ModSecurity(오픈소스, OWASP CRS 룰셋), WebKnight(IIS용 오픈소스), 상용 제품.
ModSecurity 규칙 개념
SecRuleEngine DetectionOnly # On=차단, DetectionOnly=탐지만, Off=끔
SecRequestBodyAccess On # POST 본문 검사
# 파라미터에 UNION SELECT 패턴이 있으면 403
SecRule ARGS "@rx (?i)union[\s/\*]+select" \
"id:100001,phase:2,deny,status:403,log,msg:'SQL Injection 의심'"
- 구조:
SecRule [검사 대상 변수] [연산자] [액션] - phase: 1=요청 헤더, 2=요청 본문, 3=응답 헤더, 4=응답 본문, 5=로깅
2-4. 웹 로그 분석
Apache Combined Log Format:
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
| 필드 | 의미 | 예 |
|---|---|---|
%h |
클라이언트 IP | 203.0.113.7 |
%l |
identd (거의 -) |
- |
%u |
인증 사용자 | - |
%t |
시간 | [05/Jan/2027:10:12:01 +0900] |
%r |
요청 줄(메서드 URI 프로토콜) | GET /a.php?id=1 HTTP/1.1 |
%>s |
최종 상태 코드 | 200 |
%b |
응답 바이트 | 5120 |
| Referer | 이전 페이지 | |
| User-Agent | 클라이언트 정보 | sqlmap/1.7 |
샘플 로그와 판독:
① 203.0.113.7 - - [05/Jan/2027:10:12:01 +0900] "GET /board.php?id=1%27%20AND%201=1-- HTTP/1.1" 200 5120 "-" "Mozilla/5.0"
② 203.0.113.7 - - [05/Jan/2027:10:12:02 +0900] "GET /board.php?id=1%20UNION%20SELECT%201,2,3-- HTTP/1.1" 500 312 "-" "Mozilla/5.0"
③ 198.51.100.4 - - [05/Jan/2027:10:20:11 +0900] "GET /search?q=%3Cscript%3Ealert(1)%3C/script%3E HTTP/1.1" 200 2048 "-" "Mozilla/5.0"
④ 192.0.2.9 - - [05/Jan/2027:11:00:01 +0900] "GET /admin/ HTTP/1.1" 404 196 "-" "Nikto/2.5.0"
⑤ 192.0.2.9 - - [05/Jan/2027:11:00:01 +0900] "GET /phpmyadmin/ HTTP/1.1" 404 196 "-" "Nikto/2.5.0"
⑥ 192.0.2.50 - - [05/Jan/2027:12:00:00 +0900] "GET /upload/img_93.jsp?cmd=whoami HTTP/1.1" 200 45 "-" "curl/8.0"
⑦ 192.0.2.77 - - [05/Jan/2027:12:30:00 +0900] "GET /download.php?file=..%2F..%2F..%2Fetc%2Fpasswd HTTP/1.1" 200 1734 "-" "Mozilla/5.0"
| 줄 | 판독 | 근거 |
|---|---|---|
| ①② | SQL 인젝션 시도 | %27('), AND 1=1, --, UNION SELECT. ②의 500은 컬럼 수 불일치 등 DB 오류 가능성 |
| ③ | 반사형 XSS 시도 | %3Cscript%3E = <script> |
| ④⑤ | 취약점 스캐너 | 같은 초에 다수 경로 요청, 404 다발, UA에 Nikto(그 외 sqlmap, Acunetix, Nessus, dirbuster 등) |
| ⑥ | 웹셸 실행 | 업로드 폴더의 .jsp, cmd= 파라미터, 응답 200 |
| ⑦ | 경로 조작 | ..%2F = ../, 응답 크기가 passwd 파일 크기 수준 |
- URL 인코딩 암기:
%27=',%22=",%3C=<,%3E=>,%20=공백,%2F=/,%2E=.,%0D%0A=CRLF,%00=NULL,%23=# - 주의: POST 본문은 access_log에 남지 않는다 → POST 기반 공격은 WAF 로그나 별도 설정 필요.
- 상태 코드: 200 성공, 301/302 리다이렉트, 401 인증 필요, 403 금지, 404 없음, 500 서버 오류.
- 2021판에서 XSS는 별도 항목이 아니라 A03 인젝션에 포함. "XSS가 2021 Top 10 독립 항목"이면 틀림.
- XXE는 A05 보안 설정 오류, 역직렬화는 A08 무결성 실패에 통합됨.
ServerTokens Prod는 헤더,ServerSignature Off는 오류 페이지 하단 — 역할을 바꿔 내는 문제 주의.Options Indexes(마이너스 없음)는 리스팅을 허용하는 설정이다.- WAF 포지티브 모델 = 화이트리스트(허용만 통과), 네거티브 = 블랙리스트(시그니처). 이름 때문에 헷갈리기 쉬움.
- access_log에는 GET 쿼리스트링은 남지만 POST 본문은 남지 않는다.
- TRACE 비활성화는 XST 대응(HttpOnly 쿠키를 TRACE 응답으로 읽어내는 공격).
- OWASP Top 10 2021 1위(접근 통제), 신규 3개, 통합된 항목 찾기.
- httpd.conf 지시어와 기능 연결(리스팅, 버전 숨김, 메서드 제한,
.htaccess). - 로그 한 줄을 주고 공격 종류·근거를 쓰게 하는 실기형 문제 → 인코딩 해독 + UA + 상태 코드로 판단.
- WAF의 탐지 방식(시그니처/화이트리스트)과 일반 방화벽·IPS와의 차이(HTTP 내용 검사, SSL 복호화).
확인 문제 (Day 2)
Q1. OWASP Top 10 2021에 대한 설명으로 옳지 않은 것은?
① 1위는 취약한 접근 통제이다 ② XSS는 인젝션 항목에 포함되었다 ③ SSRF는 2021년에 새로 추가되었다 ④ XXE는 독립 항목으로 4위에 위치한다
정답: ④
- ①②③ 옳음.
- ④ 틀림(정답): XXE는 2017년 A4였고, 2021년에는 A05 보안 설정 오류에 통합. 2021 A04는 안전하지 않은 설계.
Q2. Apache에서 index 파일이 없는 디렉터리에 접근할 때 파일 목록이 보이지 않도록 하는 설정은?
① ServerTokens Prod ② Options -Indexes ③ AllowOverride None ④ TraceEnable Off
정답: ②
- ① 틀림: 헤더 버전 정보 숨김.
- ② 맞음: 디렉터리 리스팅 차단.
- ③ 틀림:
.htaccess무시. - ④ 틀림: TRACE 메서드 차단.
Q3. 웹 로그에 "GET /item.php?no=3%20AND%20SLEEP(5)-- HTTP/1.1" 200이 반복적으로 기록되었다. 가장 적절한 판단은?
① 반사형 XSS 시도 ② 시간 기반 Blind SQL 인젝션 시도 ③ 디렉터리 트래버설 시도 ④ HTTP 응답 분할 시도
정답: ②
- ② 맞음:
SLEEP(5)로 응답 지연을 유도 → Time-based Blind SQLi. - ① 틀림:
<script>등 HTML 태그 없음. - ③ 틀림:
../없음. - ④ 틀림:
%0d%0a없음.
Q4. WAF에 대한 설명으로 옳지 않은 것은?
① 포지티브 보안 모델은 허용된 패턴만 통과시킨다 ② HTTPS 트래픽을 검사하려면 SSL/TLS 복호화가 필요하다 ③ 응답 내용에 포함된 개인정보 유출도 차단할 수 있다 ④ 네거티브 모델은 알려지지 않은 신규 공격 탐지에 가장 강하다
정답: ④
- ①②③ 옳음.
- ④ 틀림(정답): 네거티브(시그니처) 모델은 알려진 공격에 강하고 신규 공격(제로데이)에 약함.
Q5. Tomcat 보안 설정으로 적절하지 않은 것은?
① manager 애플리케이션을 삭제하거나 접근 IP를 제한한다 ② tomcat-users.xml의 기본 계정을 제거한다 ③ 관리 편의를 위해 DefaultServlet의 listings를 true로 설정한다 ④ shutdown 포트를 비활성화하거나 명령 문자열을 변경한다
정답: ③
- ③ 틀림(정답):
listings=true는 디렉터리 리스팅 허용 → 정보 노출.false여야 함. - ①②④ 모두 권고 설정.
Day 3 · FTP · 메일 보안
3-1. FTP 개요와 동작 모드
FTP(File Transfer Protocol)는 두 개의 TCP 연결을 씁니다.
- 제어 연결(Control): 서버 21번 포트. 명령(
USER,PASS,PORT,PASV,RETR,STOR,LIST)과 응답 코드가 오감. 세션 동안 유지. - 데이터 연결(Data): 파일·목록이 실제로 오가는 연결. 전송마다 새로 열림. 누가 누구에게 연결하느냐가 Active/Passive의 차이.
Active 모드 — "서버가 클라이언트로 접속"
sequenceDiagram
participant C as 클라이언트 (포트 N)
participant S as FTP 서버
C->>S: 제어 연결 N → 21
C->>S: PORT 명령 (내 IP, 포트 N+1 로 접속해라)
S-->>C: 200 OK
C->>S: RETR file.txt
S->>C: 데이터 연결 20 → N+1 (서버가 먼저 연결)
S-->>C: 파일 전송
Note over C: 클라이언트 방화벽/NAT가
외부에서 들어오는 연결을 막으면 실패Passive 모드 — "클라이언트가 서버로 접속"
sequenceDiagram
participant C as 클라이언트 (포트 N)
participant S as FTP 서버
C->>S: 제어 연결 N → 21
C->>S: PASV
S-->>C: 227 Entering Passive Mode (IP, 포트 P)
C->>S: 데이터 연결 N+1 → P (클라이언트가 먼저 연결)
S-->>C: 파일 전송
Note over S: 서버 방화벽에서 1024 이상
임의 포트 범위를 열어야 함| 구분 | Active | Passive |
|---|---|---|
| 데이터 연결 시작 | 서버(20번 포트에서) | 클라이언트 |
| 서버 데이터 포트 | 20 | 1024 이상 임의 포트 (서버가 PASV 응답으로 알려줌) |
| 사용 명령 | PORT |
PASV |
| 문제가 되는 쪽 | 클라이언트 방화벽·NAT | 서버 방화벽(포트 범위 개방 필요) |
| 현재 일반적 | 덜 씀 | 기본값인 경우 많음 |
FTP 관련 프로토콜 비교
| 프로토콜 | 포트 | 특징 |
|---|---|---|
| FTP | TCP 21(제어), 20(Active 데이터) | 평문 (계정·비밀번호 스니핑 가능) |
| TFTP | UDP 69 | 인증 없음, 디렉터리 목록 X, 단순. 네트워크 장비 설정·부팅(PXE)에 사용. tftpd -s(secure 모드)로 특정 디렉터리 제한 |
| SFTP | TCP 22 | SSH 기반, FTP와 다른 프로토콜. 단일 연결, 암호화 |
| FTPS | 21(명시적, AUTH TLS) / 990(암시적) | FTP + SSL/TLS |
| SCP | TCP 22 | SSH 기반 복사 |
3-2. FTP 공격과 대응
FTP Bounce 공격
FTP 프로토콜은 PORT 명령에 클라이언트 자신이 아닌 다른 IP를 적는 것을 원래 막지 않았습니다(서버 간 직접 전송 기능 때문). 공격자는 이를 악용해 FTP 서버를 중간 다리로 삼아 제3의 호스트에 연결하게 만듭니다.
sequenceDiagram
participant A as 공격자
participant F as FTP 서버 (중계)
participant T as 피해 호스트 (내부)
A->>F: 로그인 (익명 등)
A->>F: PORT 피해호스트IP, 포트X
A->>F: LIST 또는 RETR
F->>T: 데이터 연결 시도 → 포트X
T-->>F: 연결 성공 또는 거부
F-->>A: 150/425 응답으로 포트 개방 여부 노출
Note over A: 공격자 IP 숨긴 포트 스캔, 방화벽 우회
업로드한 파일 내용을 다른 서비스에 명령처럼 전송- 악용: 포트 스캔(출발지가 FTP 서버로 보임 → 공격자 은닉), 방화벽 우회(FTP 서버가 내부망에 있을 때), 다른 서비스로 데이터 주입
- 대응:
PORT명령의 IP가 제어 연결의 클라이언트 IP와 같은지 확인, 1024 미만 포트 지정 거부, 익명 FTP 쓰기 금지, 가능하면 Passive 사용
기타 FTP 위협
| 위협 | 내용 | 대응 |
|---|---|---|
| Anonymous FTP | anonymous/ftp 계정으로 누구나 접속. 쓰기 가능하면 불법 자료·악성코드 저장소(warez) |
불필요 시 비활성화, 필요 시 읽기 전용, 업로드 디렉터리는 쓰기만(읽기 X) |
| 평문 스니핑 | 계정·파일 노출 | SFTP/FTPS |
| 무차별 대입 | 비밀번호 추측 | 실패 제한, 강한 비밀번호 |
| TFTP 정보 탈취 | 인증 없이 설정 파일·/etc/passwd 다운로드 |
불필요 시 비활성화, secure 모드, 접근 IP 제한 |
| 상위 디렉터리 탈출 | 사용자가 전체 파일 시스템 탐색 | chroot(홈 디렉터리에 가두기) |
| 배너 정보 노출 | 서버 버전 노출 | 배너 변경 |
ftpusers / vsftpd 설정
# /etc/ftpusers (vsftpd는 /etc/vsftpd/ftpusers)
# ★ 이 파일에 적힌 계정은 FTP 접속 "거부"
root
bin
daemon
adm
nobody
# /etc/vsftpd/vsftpd.conf
anonymous_enable=NO # 익명 접속 금지
local_enable=YES # 로컬 계정 로그인 허용
write_enable=YES # 업로드 허용 여부
chroot_local_user=YES # 로컬 사용자를 홈 디렉터리에 가둠
userlist_enable=YES
userlist_deny=YES # user_list에 있는 계정 거부 (NO면 반대로 그 계정만 허용)
xferlog_enable=YES # 전송 로그 기록
xferlog_file=/var/log/xferlog
ftpd_banner=Authorized users only. # 버전 대신 경고 문구
pasv_min_port=50000 # Passive 데이터 포트 범위 (방화벽과 일치시킴)
pasv_max_port=50100
ssl_enable=YES # FTPS
- xferlog: FTP 전송 기록(시간, 원격 호스트, 파일명, 크기, 방향
i/o, 사용자 등) userlist_deny=YES+user_list: 목록 계정 차단 /userlist_deny=NO: 목록 계정만 허용 — 반대로 묻는 문제 주의
3-3. 메일 시스템 개요
sequenceDiagram
participant U1 as 송신자 MUA (Outlook)
participant M1 as 송신 MTA
participant M2 as 수신 MTA
participant D as MDA (메일함 저장)
participant U2 as 수신자 MUA
U1->>M1: SMTP 제출 (587, 인증)
M1->>M1: DNS에서 수신 도메인 MX 조회
M1->>M2: SMTP 전달 (25)
M2->>D: 로컬 전달
D->>D: 메일함 저장
U2->>D: POP3 (110/995) 또는 IMAP (143/993) 로 가져오기
D-->>U2: 메일| 구성요소 | 역할 | 예 |
|---|---|---|
| MUA (Mail User Agent) | 사용자가 메일 작성·읽기 | Outlook, Thunderbird |
| MTA (Mail Transfer Agent) | 메일 전송·중계 (SMTP) | Sendmail, Postfix, Exchange |
| MDA (Mail Delivery Agent) | 수신 메일을 메일함에 배달 | Procmail, Dovecot LDA |
| MSA | MUA로부터 메일 제출 받음(587) |
| 프로토콜 | 포트(평문/암호) | 특징 |
|---|---|---|
| SMTP | 25 / (465 SMTPS), 587(제출, STARTTLS) | 메일 송신·서버 간 전달 |
| POP3 | 110 / 995 | 메일을 다운로드 후 서버에서 삭제(기본). 단일 기기 |
| IMAP | 143 / 993 | 메일을 서버에 보관, 여러 기기 동기화, 폴더 관리 |
SMTP 주요 명령: HELO/EHLO, MAIL FROM, RCPT TO, DATA, QUIT, VRFY(사용자 존재 확인), EXPN(메일링 리스트 확장 → 실제 계정 목록), STARTTLS.
3-4. 메일 보안 기술: PGP · S/MIME · PEM
PGP (Pretty Good Privacy)
필 짐머만(Phil Zimmermann)이 만든 개인용 메일·파일 보안 프로그램. 중앙 인증기관 없이, 사용자들이 서로의 공개키에 서명해 주는 **신뢰의 웹(Web of Trust)**으로 키를 신뢰.
PGP 5대 서비스:
| 서비스 | 방법 |
|---|---|
| 인증(전자서명) | 메시지 해시(SHA-1/MD5) → 송신자 개인키로 서명(RSA/DSS) |
| 기밀성 | 일회용 세션키로 메시지 대칭 암호화(IDEA/3DES/CAST-128/AES) → 세션키를 수신자 공개키로 암호화(전자봉투) |
| 압축 | ZIP. 서명 후 압축, 암호화 전 압축 |
| 전자메일 호환성 | Radix-64(Base64) 변환 → 바이너리를 ASCII로 |
| 세그먼테이션 | 큰 메시지 분할 |
PGP 송신 처리 순서:
원문 → [해시+개인키 서명] → [ZIP 압축] → [세션키 대칭 암호화 + 세션키를 수신자 공개키로 암호화] → [Radix-64] → 전송
- 왜 서명 후 압축? 서명 검증 시 압축 알고리즘 버전에 영향받지 않도록.
- 왜 암호화 전 압축? 중복(패턴)이 줄어 암호 강도↑, 크기↓.
| 구분 | PGP | S/MIME | PEM |
|---|---|---|---|
| 개발 | 개인(짐머만) → OpenPGP 표준 | RSA Data Security → IETF 표준 | IETF |
| 신뢰 모델 | 신뢰의 웹 (분산) | PKI·X.509 인증서 (계층, CA) | 중앙집중식 계층 인증 |
| 키 관리 | 사용자 직접 | CA가 인증서 발급 | 엄격한 CA 계층 |
| 적용 | 개인, 파일 암호화 | 기업·표준 메일 클라이언트 내장 | 군사·금융 등 고보안 지향, 구현 복잡해 거의 사용 안 함 |
| 형식 | Radix-64 | MIME 확장, CMS(PKCS#7) | 텍스트 기반 |
| 특징 | 쉽고 무료 | 대부분 메일 클라이언트 지원 | 높은 보안성, 낮은 보급 |
3-5. 스팸·스푸핑 대응: SPF · DKIM · DMARC
| 기술 | 무엇을 검증 | 어떻게 | DNS 레코드 |
|---|---|---|---|
| SPF | 메일을 보낸 서버 IP가 그 도메인이 허가한 서버인가 | 수신 MTA가 봉투 발신 도메인(MAIL FROM)의 SPF 레코드 조회 → 연결 IP와 비교 | 도메인 TXT |
| DKIM | 메일 헤더·본문이 위변조되지 않았고 도메인이 서명했는가 | 송신 MTA가 개인키로 서명(DKIM-Signature 헤더), 수신 측이 DNS의 공개키로 검증 | 셀렉터._domainkey.도메인 TXT |
| DMARC | SPF/DKIM 결과가 **헤더 From 도메인과 일치(정렬)**하는가 + 실패 시 처리 정책 | p=none/quarantine/reject, 보고서(rua) |
_dmarc.도메인 TXT |
sequenceDiagram
participant S as 송신 MTA (example.com)
participant R as 수신 MTA
participant N as DNS
S->>R: SMTP로 메일 전달 (DKIM 서명 포함)
R->>N: example.com TXT 조회 (SPF)
N-->>R: v=spf1 ip4:203.0.113.0/24 -all
R->>R: 연결 IP가 범위 안인가 → SPF 결과
R->>N: sel1._domainkey.example.com TXT 조회
N-->>R: DKIM 공개키
R->>R: 서명 검증 → DKIM 결과
R->>N: _dmarc.example.com TXT 조회
N-->>R: p=reject 정책
R->>R: From 도메인 정렬 확인 후 정책 적용 (수신/격리/거부)
R-->>S: 집계 보고서는 나중에 rua 주소로 발송DNS TXT 레코드 예:
example.com. IN TXT "v=spf1 ip4:203.0.113.0/24 include:_spf.mailvendor.example -all"
sel1._domainkey.example.com. IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqh...(공개키)"
_dmarc.example.com. IN TXT "v=DMARC1; p=reject; rua=mailto:dmarc-report@example.com; pct=100"
- SPF 한정자:
-all(나머지 거부, Fail),~all(Softfail, 의심 표시),?all(중립),+all(모두 허용 — 쓰면 안 됨) - DMARC 정책:
none(모니터링만) →quarantine(스팸함 격리) →reject(거부)
기타 스팸 대책:
- RBL(Real-time Blackhole List, DNSBL): 스팸 발송 IP 목록을 DNS로 조회해 차단
- 그레이리스팅: 처음 보는 발신자에게 임시 거부(4xx) → 정상 MTA는 재전송, 스팸봇은 대부분 재전송 안 함
- SpamAssassin: 규칙·베이지안 필터로 점수 매겨 임계치 초과 시 스팸
- 역방향 DNS(PTR) 확인, 발송량 제한
3-6. 메일 서버 공격과 설정
| 공격 | 설명 | 대응 |
|---|---|---|
| 오픈 릴레이 | 외부인이 우리 서버를 통해 외부로 메일 중계 → 스팸 발송지로 악용, RBL 등재 | 릴레이 제한: 내부 네트워크·인증 사용자만 |
| EXPN / VRFY | 계정 존재·메일링 리스트 구성원 확인 → 계정 수집 | 명령 비활성화 |
| 메일 폭탄 | 대량·대용량 메일로 메일함·디스크 고갈 | 메시지 크기·수신 수 제한, 발신자 차단 |
| 스푸핑 | 발신자 위조 | SPF·DKIM·DMARC |
| 악성 첨부·피싱 | 실행 파일, 매크로 문서 | 첨부 필터링, 샌드박스 |
| 스니핑 | 평문 SMTP/POP3 | STARTTLS, SMTPS/POP3S/IMAPS |
Sendmail 개념 설정:
# /etc/mail/sendmail.cf
O PrivacyOptions=authwarnings,novrfy,noexpn,restrictqrun # VRFY·EXPN 차단, 일반 사용자 큐 실행 제한
O MaxMessageSize=10485760 # 메일 크기 제한(메일 폭탄 완화)
# /etc/mail/access (makemap hash access < access 로 DB 생성)
localhost RELAY
192.168.10 RELAY # 내부망만 릴레이 허용
spam.example REJECT
- Sendmail 8.9 이후 기본적으로 릴레이 거부.
promiscuous_relay같은 기능 활성화는 오픈 릴레이를 만든다. - 버전 배너(
SmtpGreetingMessage) 정보 최소화.
Postfix 개념 설정:
# /etc/postfix/main.cf
mynetworks = 127.0.0.0/8, 192.168.10.0/24
smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
disable_vrfy_command = yes
message_size_limit = 10485760
smtpd_banner = $myhostname ESMTP
reject_unauth_destination: 우리 도메인이 목적지가 아니고, 내부/인증 사용자도 아니면 중계 거부 → 오픈 릴레이 방지 핵심.
- ftpusers에 적힌 계정은 "허용"이 아니라 "거부". root를 반드시 넣는다.
- Active 모드 데이터 연결은 서버 20번 → 클라이언트. Passive는 클라이언트 → 서버 임의 포트. "Passive에서 서버가 20번 사용"은 틀림.
- SFTP(SSH, 22)와 FTPS(FTP+TLS)는 다른 프로토콜.
- TFTP는 UDP 69, 인증 없음. TCP라고 하면 틀림.
- POP3는 기본적으로 다운로드 후 서버에서 삭제, IMAP은 서버 보관.
- PGP는 신뢰의 웹, S/MIME은 X.509 PKI. PGP 처리 순서는 서명 → 압축 → 암호화 → Radix-64.
- SPF는 IP, DKIM은 전자서명, DMARC는 정책+보고+정렬. DKIM은 메일 본문을 암호화하지 않는다(무결성·출처 인증).
- 오픈 릴레이 문제는 "외부 → 외부" 중계. 외부에서 우리 도메인 사용자에게 오는 메일 수신은 정상.
- Active/Passive 연결 방향, 포트 번호, 방화벽 문제 위치 비교.
- FTP Bounce의 원리(
PORT명령 악용)와 용도(포트 스캔·우회). - ftpusers·vsftpd 설정 항목 의미, xferlog.
- PGP 서비스 항목·처리 순서, PGP vs S/MIME vs PEM 비교.
- SPF/DKIM/DMARC의 역할 구분, TXT 레코드 보고 의미 해석.
- Sendmail에서
EXPN·VRFY제한, 릴레이 제한(access파일).
확인 문제 (Day 3)
Q1. FTP Passive 모드에 대한 설명으로 옳은 것은?
① 서버가 20번 포트에서 클라이언트로 데이터 연결을 시작한다 ② 클라이언트가 PORT 명령으로 자신의 포트를 알려준다 ③ 클라이언트가 서버가 알려준 임의 포트로 데이터 연결을 시작한다 ④ 클라이언트 측 방화벽이 외부 유입 연결을 막아 실패하기 쉽다
정답: ③
- ①②④ 틀림: 모두 Active 모드 설명.
- ③ 맞음:
PASV→ 서버가 227 응답으로 포트 안내 → 클라이언트가 연결.
Q2. FTP Bounce 공격에 악용되는 명령은?
① PASV ② PORT ③ RETR ④ STOR
정답: ②
- ② 맞음:
PORT에 제3자 IP·포트를 지정하여 FTP 서버가 그곳으로 연결하게 함. - ① 서버 포트를 요청하는 명령. ③ 다운로드, ④ 업로드 — 공격 흐름의 일부일 수는 있으나 핵심은 PORT.
Q3. vsftpd 및 FTP 보안 설정 설명으로 옳지 않은 것은?
① anonymous_enable=NO로 익명 접속을 막는다 ② chroot_local_user=YES는 사용자를 홈 디렉터리에 제한한다 ③ ftpusers 파일에 등록된 계정만 FTP 접속이 허용된다 ④ xferlog는 파일 전송 기록을 남긴다
정답: ③
- ③ 틀림(정답): ftpusers 등록 계정은 접속 거부 대상.
- ①②④ 옳음.
Q4. PGP에 대한 설명으로 옳지 않은 것은?
① 공개키 신뢰를 위해 신뢰의 웹을 사용한다 ② 바이너리 데이터를 Radix-64로 변환해 메일 호환성을 제공한다 ③ 압축은 암호화를 수행한 다음에 한다 ④ 메시지 암호화에는 일회용 세션키를 사용한다
정답: ③
- ③ 틀림(정답): 암호화 전에 압축한다. 암호문은 무작위성이 커 압축 효과가 거의 없음.
- ①②④ 옳음.
Q5. 수신 메일 서버가 "발신 도메인의 DNS에 등록된 허가 IP 목록과 실제 연결 IP를 비교"하는 기술은?
① DKIM ② DMARC ③ SPF ④ S/MIME
정답: ③
- ③ 맞음: SPF는 발송 서버 IP 검증.
- ① 틀림: DKIM은 전자서명으로 위변조 검증.
- ② 틀림: DMARC는 SPF·DKIM 결과의 정렬 확인과 처리 정책.
- ④ 틀림: S/MIME은 사용자 단위 메일 암호화·서명.
Q6. 메일 서버에서 공격자가 계정 존재 여부를 확인하는 데 쓰일 수 있어 비활성화를 권고하는 SMTP 명령의 조합은?
① HELO, EHLO ② MAIL FROM, RCPT TO ③ EXPN, VRFY ④ DATA, QUIT
정답: ③
- ③ 맞음:
VRFY는 사용자 확인,EXPN은 메일링 리스트 확장 → 계정 수집에 악용. - ①②④ 메일 전송에 필수적인 기본 명령.
Day 4 · DNS · DB 보안
4-1. DNS 개요
DNS는 도메인 이름을 IP 주소로 바꿔 주는 분산 계층형 데이터베이스입니다. 기본은 UDP 53, 응답이 크거나(기존 512바이트 초과, EDNS0 미사용 시) **존 전송(Zone Transfer)**일 때는 TCP 53을 사용합니다.
주요 레코드
| 레코드 | 의미 | 예 |
|---|---|---|
| A | 이름 → IPv4 | www IN A 203.0.113.10 |
| AAAA | 이름 → IPv6 | www IN AAAA 2001:db8::10 |
| CNAME | 별칭 → 정식 이름 | blog IN CNAME www.example.com. |
| MX | 메일 서버 (우선순위 숫자 작을수록 우선) | IN MX 10 mail.example.com. |
| NS | 해당 존의 권한 네임서버 | IN NS ns1.example.com. |
| PTR | 역방향: IP → 이름 (in-addr.arpa) |
10.113.0.203.in-addr.arpa. IN PTR www.example.com. |
| SOA | 존의 권한 시작: 주 네임서버, 관리자 메일, Serial, Refresh, Retry, Expire, Minimum TTL | |
| TXT | 임의 텍스트 (SPF, DKIM, DMARC, 도메인 소유 인증) | |
| SRV | 서비스 위치(포트 포함) | _sip._tcp |
| CAA | 이 도메인에 인증서 발급 가능한 CA 지정 |
- SOA의 Serial이 증가해야 보조 DNS가 존 전송을 받음 (Refresh 주기마다 Serial 비교).
재귀(Recursive) vs 반복(Iterative) 질의
sequenceDiagram
participant C as 클라이언트 (Stub)
participant L as 로컬 DNS (리졸버)
participant R as 루트 DNS
participant T as .com TLD DNS
participant A as example.com 권한 DNS
C->>L: www.example.com? (재귀 질의 - 최종 답을 달라)
L->>R: www.example.com? (반복 질의)
R-->>L: 모름, .com NS는 여기 (Referral)
L->>T: www.example.com?
T-->>L: 모름, example.com NS는 여기
L->>A: www.example.com?
A-->>L: A 203.0.113.10 (권한 응답)
L->>L: TTL 동안 캐시 저장
L-->>C: 203.0.113.10| 구분 | 재귀 질의 | 반복 질의 |
|---|---|---|
| 구간 | 클라이언트 → 로컬 DNS | 로컬 DNS → 루트/TLD/권한 DNS |
| 의미 | "최종 답을 찾아서 줘" | "아는 만큼(다음 서버 위치)만 알려줘" |
| 부담 | 로컬 DNS가 모든 일을 함 | 각 서버는 참조(Referral)만 반환 |
- 클라이언트 쪽 이름 해석 순서: (OS별 차이 있으나 일반적으로) hosts 파일 → 로컬 DNS 캐시 → DNS 서버 질의. hosts 파일 변조 = 파밍의 대표 수법.
4-2. DNS 공격
| 공격 | 원리 | 대응 |
|---|---|---|
| DNS 스푸핑 | 같은 네트워크에서 질의를 엿보고 정상 응답보다 먼저 위조 응답 전송(ARP 스푸핑과 결합) | DNSSEC, 네트워크 분리, ARP 보호 |
| 캐시 포이즈닝 | 리졸버 캐시에 위조 레코드 주입 → 그 리졸버 쓰는 모든 사용자 피해 | 출발지 포트 랜덤화, DNSSEC, 재귀 제한 |
| 카민스키 공격 | 캐시 포이즈닝 고도화 (아래) | 포트 랜덤화 + DNSSEC |
| DNS 증폭 DDoS | 출발지 IP를 피해자로 위조하여 오픈 리졸버에 작은 질의(ANY, DNSSEC 큰 응답) → 큰 응답이 피해자에게 | 오픈 재귀 차단, RRL(응답 속도 제한), 위조 IP 필터링(BCP38) |
| DNS 터널링 | 데이터를 서브도메인 이름·TXT 응답에 인코딩해 방화벽 우회·유출·C&C | 긴/무작위 서브도메인, 특정 도메인 TXT 질의 급증 탐지, DNS 방화벽 |
| 존 전송 정보 유출 | AXFR 허용 시 존 전체(내부 호스트명·IP) 획득 → 정찰 |
allow-transfer 보조 DNS만, TSIG |
| 파밍 | hosts 변조·DNS 변조로 정상 주소 입력해도 가짜 사이트 | hosts 무결성 감시, DNSSEC, HTTPS 인증서 확인 |
| DNS 서버 DoS | 랜덤 서브도메인 대량 질의(Water Torture) | 질의 제한, Anycast |
캐시 포이즈닝과 카민스키 공격
일반 캐시 포이즈닝: 리졸버가 권한 서버에 질의를 보낸 순간, 공격자가 16비트 Transaction ID(그리고 출발지 포트)를 맞춘 위조 응답을 진짜보다 먼저 보내면 캐시에 저장됩니다. 하지만 한 번 실패하면 정상 응답이 TTL 동안 캐시되어 재시도가 어렵습니다.
**카민스키 공격(2008)**은 이 한계를 깼습니다.
sequenceDiagram
participant A as 공격자
participant L as 피해 리졸버
participant N as bank.example 권한 DNS
A->>L: rnd001.bank.example? (존재하지 않는 이름)
L->>N: rnd001.bank.example? (TXID 추측 대상)
A-->>L: 위조 응답 다량 (TXID 추측)
Note over A,L: 위조 응답의 권한(Authority) 영역에
bank.example NS = 공격자 서버 를 끼워 넣음
N-->>L: 정상 응답 (늦으면 무시됨)
A->>L: 실패 시 rnd002.bank.example? 로 즉시 재시도
Note over L: 매번 새 이름이라 캐시에 막히지 않음
성공하면 도메인 전체가 공격자 NS로 위임됨- 핵심: ① 매번 존재하지 않는 서브도메인을 질의 → 캐시 방해 없이 무한 재시도, ② 위조 응답에 NS(권한) 레코드를 넣어 도메인 전체를 탈취.
- 대응: 출발지 포트 랜덤화(TXID 16비트 + 포트 약 16비트로 추측 공간 확대), DNSSEC(근본), 재귀 질의 허용 대상 제한, 0x20 대소문자 랜덤화.
4-3. DNSSEC
DNSSEC은 DNS 응답에 전자서명을 붙여, 리졸버가 **"이 응답이 진짜 그 존 관리자가 만든 것이고 중간에 변조되지 않았다"**를 검증하게 합니다.
| 레코드 | 역할 |
|---|---|
| RRSIG | 레코드 집합(RRset)에 대한 전자서명 |
| DNSKEY | 존의 공개키 (ZSK: 레코드 서명용, KSK: DNSKEY 집합 서명용) |
| DS (Delegation Signer) | 자식 존 KSK의 해시를 부모 존에 등록 → 신뢰 연결 고리 |
| NSEC / NSEC3 | 존재하지 않음을 서명으로 증명 (NSEC3는 이름을 해시해 존 워킹(존 내용 열거) 완화) |
신뢰 체인(Chain of Trust):
[루트 존] 신뢰 앵커(루트 KSK, 리졸버에 미리 설정)
│ 루트 DNSKEY ──서명──▶ 루트 존의 ".com DS" (RRSIG)
▼
[.com 존] .com DNSKEY ← 해시가 루트의 DS와 일치하는지 확인
│ .com DNSKEY ──서명──▶ .com 존의 "example.com DS" (RRSIG)
▼
[example.com 존] example.com DNSKEY(KSK) ← 해시가 .com의 DS와 일치
│ KSK ──서명──▶ DNSKEY 집합 (ZSK 포함)
│ ZSK ──서명──▶ www.example.com A 레코드 (RRSIG)
▼
리졸버: 루트부터 차례로 검증 성공 → 응답 신뢰 (AD 플래그)
| DNSSEC이 제공하는 것 | DNSSEC이 제공하지 않는 것 |
|---|---|
| 데이터 출처 인증 | 기밀성(질의·응답 암호화 X → DoT/DoH가 담당) |
| 데이터 무결성 | DoS/DDoS 방어 (오히려 응답이 커져 증폭에 악용 가능) |
| 부재 증명(NSEC/NSEC3) | 검증하지 않는 클라이언트·리졸버 구간 보호 |
| 캐시 포이즈닝·스푸핑 방어 | 서버 자체 침해·잘못된 데이터 입력 방지 |
4-4. BIND 보안 설정
// /etc/named.conf
options {
directory "/var/named";
version "unknown"; // 버전 정보 숨김 (version.bind 질의 대응)
allow-query { any; }; // 권한 존에 대한 일반 질의
allow-recursion { 127.0.0.1; 10.0.0.0/8; }; // 재귀는 내부 사용자만 (오픈 리졸버 방지)
allow-transfer { 192.0.2.53; }; // 존 전송은 보조 DNS만
dnssec-validation auto; // DNSSEC 검증
rate-limit { responses-per-second 10; }; // RRL: 증폭 공격 완화
};
// 권한 전용 서버라면 recursion no; 로 재귀 자체를 끈다
// TSIG 키로 존 전송 인증
key "xfer-key" { algorithm hmac-sha256; secret "base64키값"; };
zone "example.com" {
type master;
file "example.com.zone";
allow-transfer { key "xfer-key"; };
allow-update { none; }; // 동적 업데이트 금지
};
점검 명령 개념:
dig @ns1.example.com example.com AXFR→ 존 전송이 외부에 허용되는지 확인dig @ns1.example.com version.bind chaos txt→ 버전 노출 여부- BIND 실행은 비특권 계정(
named -u named), chroot 환경 권장
4-5. DB 보안 개요와 접근 통제
DBMS 보안 요구사항: 부적절한 접근 방지, 추론 방지, DB 무결성 보장, 데이터 운영적·의미적 무결성, 감사 기능, 사용자 인증, 민감 데이터 관리, 다단계(MLS) 보호.
GRANT / REVOKE / ROLE / VIEW
-- 역할 생성 후 권한 부여 (사용자에게 직접보다 역할로 관리)
CREATE ROLE hr_reader;
GRANT SELECT ON hr.employee_public TO hr_reader;
GRANT hr_reader TO kim;
-- 권한 위임 가능하게 부여
GRANT SELECT, UPDATE ON hr.employee TO lee WITH GRANT OPTION;
-- 회수: CASCADE면 lee가 다른 사람에게 준 권한도 연쇄 회수
REVOKE UPDATE ON hr.employee FROM lee CASCADE;
-- 뷰로 민감 컬럼(주민번호·연봉) 숨기고 행도 제한
CREATE VIEW hr.employee_public AS
SELECT emp_id, name, dept
FROM hr.employee
WHERE dept <> 'EXEC'
WITH CHECK OPTION; -- 뷰 조건을 벗어나는 INSERT/UPDATE 금지
| 도구 | 효과 |
|---|---|
GRANT / REVOKE |
객체(테이블·뷰·프로시저) 단위 권한 부여·회수 |
WITH GRANT OPTION |
받은 권한을 남에게 재부여 가능 → 남용 시 통제 상실, 꼭 필요할 때만 |
CASCADE |
연쇄 회수 |
| ROLE | 권한 묶음 → 관리 단순화, 최소 권한 |
| VIEW | 열·행 수준 접근 제한, 원본 테이블 구조 은닉 |
| 저장 프로시저 | 테이블 직접 접근 대신 정해진 작업만 실행 권한 |
기본 보안 수칙: 기본 계정·샘플 스키마 제거 또는 비밀번호 변경(과거 Oracle scott/tiger, MSSQL sa 빈 비밀번호 사례), 리스너·관리 포트 접근 IP 제한, 원격 접속 제한, 최신 패치, 앱 계정 최소 권한, PUBLIC에 부여된 불필요 권한 회수.
4-6. DB 고유 위협: 추론 · 집성 · 다중 인스턴스화
추론(Inference)
**허용된 정보(특히 통계 질의)**를 조합해 허용되지 않은 개별 정보를 알아내는 것.
허용: 통계 질의(평균·합계)만 가능, 개인 연봉 조회 불가
Q1: SELECT AVG(salary) FROM emp WHERE dept='보안팀'; → 6,000
Q2: SELECT COUNT(*) FROM emp WHERE dept='보안팀'; → 1
결론: 보안팀은 1명 → 그 사람의 연봉은 6,000 (개별 정보 유출)
트래커(Tracker) 변형:
Q3: SUM(salary) WHERE dept='보안팀' OR dept='개발팀'
Q4: SUM(salary) WHERE dept='개발팀'
Q3 - Q4 = 보안팀 합계 → 결과 집합 크기 제한을 우회
- 대응: 최소 결과 집합 크기 제한(n명 미만이면 응답 거부), 셀 억제, 결과에 노이즈(교란) 추가, 질의 이력 감사, 데이터 분할, 다중 인스턴스화
집성(Aggregation)
개별로는 낮은 등급인 정보를 모으면 높은 등급의 의미를 갖게 되는 것.
부대 A 위치 = 대외비, 부대 B 위치 = 대외비, ... 부대 Z 위치 = 대외비
→ 전부 모으면 "전체 병력 배치도" = 비밀
- 대응: 데이터 집합 자체를 더 높은 등급으로 분류, 사용자가 이미 조회한 내용에 따라 추가 접근을 제한(문맥 기반 접근 통제), 질의량 제한
| 구분 | 추론 | 집성 |
|---|---|---|
| 방식 | 논리적 유추(계산·조합) | 단순 수집(모으기) |
| 출발 정보 | 허용된 정보(통계 등) | 낮은 등급 정보 다수 |
| 결과 | 숨겨진 개별 값 노출 | 상위 등급 의미 발생 |
다중 인스턴스화(Polyinstantiation)
다단계 보안(MLS) DB에서 같은 기본키를 가진 레코드가 보안 등급별로 서로 다른 내용을 갖도록 하는 것.
| 함선(기본키) | 임무 | 등급 |
|---|---|---|
| 한빛호 | 정찰 작전 | 비밀 |
| 한빛호 | 해상 훈련 | 일반 |
- 일반 등급 사용자가 "한빛호" 레코드를 새로 입력하려 할 때, 이미 비밀 레코드가 있다고 거부하면 → "높은 등급 정보가 있다"는 사실을 추론할 수 있음. 그래서 일반 등급용 레코드(위장 정보, cover story)를 따로 둠.
- 목적: 추론 공격 방지, 하위 사용자에게 상위 정보 존재 은닉.
4-7. DB 암호화
암호화 위치 그림
[사용자] → [WAS / 애플리케이션] → [DBMS 엔진] → [OS 파일 시스템] → [디스크]
▲ ▲ ▲ ▲
│ │ │ │
① API 방식 ② 플러그인 ③ TDE ④ 파일(OS) 암호화
(앱에서 암호화 후 (DB 안 암호화 (DBMS 커널이 (OS 드라이버가
DB에 저장) 함수·뷰 이용) 블록 I/O 시 파일 단위로)
자동 암복호화)
| 방식 | 암·복호화 위치 | 앱 수정 | 성능 부하 | 장점 | 단점 |
|---|---|---|---|---|---|
| API | 애플리케이션 서버 | 많음 | DB 부하 적음(앱 서버 부하) | DB 종류 무관, 세밀한 제어 | 소스 수정 필요, 개발 부담 |
| 플러그인 | DB 서버(암호화 모듈·UDF, 뷰·트리거) | 적음 | DB 서버 부하 | 앱 변경 최소 | DB 부하, 색인 검색 성능 저하 |
| TDE | DBMS 커널 (데이터 블록 저장 시) | 없음 | 비교적 적음 | 투명, 성능 우수 | DBMS 종속, 커널 기능 필요 |
| 파일 암호화 | OS (파일 단위) | 없음 | 적음 | DB 외 파일(로그·백업)도 | 접근 권한 있는 DB 사용자에게는 평문으로 보임 → 컬럼 단위 통제 X |
| 하이브리드 | API + 플러그인 혼합 | 중간 | 분산 | 장점 결합 | 복잡 |
- 키 관리가 핵심: 암호화 키는 DB와 분리된 저장소(HSM, KMS)에.
- 개인정보 안전성 확보조치 관점: 고유식별정보·비밀번호·바이오정보 등은 암호화 대상, 비밀번호는 일방향(해시) 암호화.
4-8. DB 접근제어 솔루션과 감사
| 방식 | 구성 | 장점 | 단점 |
|---|---|---|---|
| 게이트웨이(프록시) | 사용자와 DB 사이에 별도 서버, 모든 질의가 경유 | 강력한 실시간 차단, DB 영향 적음 | 단일 장애점, 경로 우회(직접 접속) 가능성, 성능 병목 |
| 에이전트 | DB 서버에 에이전트 설치 | 로컬 접속까지 통제, 우회 어려움 | DB 서버 부하, DBMS·OS 종속, 설치 부담 |
| 스니핑(패시브) | 네트워크 미러링(TAP/SPAN)으로 감시만 | 성능 영향 없음, 설치 쉬움 | 실시간 차단 어려움(TCP Reset 정도), 로컬 접속·암호화 트래픽 감시 불가 |
| 하이브리드 | 조합 | 보완 | 복잡 |
- DB 감사(Audit): 누가 언제 무엇을 조회·변경했는지 기록. 예:
AUDIT SELECT ON hr.employee BY ACCESS;(Oracle 표준 감사), 세밀한 감사(FGA)는 특정 조건 컬럼 접근만 기록. 감사 로그는 DBA가 임의로 지울 수 없도록 분리 보관. - 트랜잭션 ACID: 원자성(Atomicity, 전부 아니면 전무), 일관성(Consistency), 고립성(Isolation, 동시 실행 간섭 없음), 지속성(Durability, 커밋되면 영구).
- 클라이언트→로컬 DNS가 재귀, 로컬 DNS→루트/TLD/권한이 반복. 반대로 내는 문제 단골.
- DNSSEC은 기밀성·가용성(DoS 방어)을 제공하지 않는다. 무결성·출처 인증·부재 증명만.
- DS 레코드는 부모 존에 있다(자식 KSK의 해시). DNSKEY는 자기 존에.
- 존 전송은 TCP 53, 일반 질의는 주로 UDP 53.
- 카민스키 공격의 핵심은 존재하지 않는 서브도메인 반복 + NS 레코드 위조. 실무 1순위 조치는 출발지 포트 랜덤화, 근본은 DNSSEC.
- 추론 = 유추, 집성 = 수집. 다중 인스턴스화는 추론 방지책.
- TDE는 앱 수정 없음, API 방식은 앱 수정 많음. 파일 암호화는 DB 권한자에게는 평문으로 보인다.
- 스니핑 방식 DB 접근제어는 차단이 약하다. 게이트웨이는 우회 접속에 약하다.
- DNS 레코드 용도(MX, PTR, SOA, CNAME) 고르기.
- named.conf 지시어
allow-transfer,allow-recursion,version,recursion no의미. - DNSSEC 레코드 4종 역할, DNSSEC 한계(기밀성·DoS).
- DNS 증폭 공격 원리(위조 출발지 + 오픈 리졸버 + 큰 응답).
- 추론·집성·다중 인스턴스화 정의를 시나리오로 구분.
- DB 암호화 방식 비교(앱 수정, 부하, 위치), DB 접근제어 방식 장단점.
확인 문제 (Day 4)
Q1. 다음 중 DNSSEC이 제공하는 보안 서비스가 아닌 것은?
① 데이터 무결성 ② 데이터 출처 인증 ③ 질의·응답 내용의 기밀성 ④ 존재하지 않는 도메인에 대한 인증된 부재 증명
정답: ③
- ③ 틀림(정답): DNSSEC은 서명만 할 뿐 암호화하지 않음. 기밀성은 DoT/DoH.
- ①② RRSIG·DNSKEY로 제공. ④ NSEC/NSEC3로 제공.
Q2. DNSSEC에서 자식 존 KSK 공개키의 해시값을 부모 존에 등록하여 신뢰 체인을 연결하는 레코드는?
① RRSIG ② DNSKEY ③ DS ④ NSEC3
정답: ③
- ③ 맞음: DS(Delegation Signer)는 부모 존에 있으며 자식 KSK의 해시.
- ① 서명값. ② 공개키 자체. ④ 부재 증명(해시 기반).
Q3. BIND에서 존 전송을 보조 네임서버로만 제한하는 설정은?
① allow-query ② allow-recursion ③ allow-transfer ④ allow-update
정답: ③
- ① 질의 허용 대상. ② 재귀 질의 허용 대상(오픈 리졸버 방지). ④ 동적 업데이트 허용 대상.
- ③ 맞음: AXFR/IXFR 허용 대상.
Q4. 통계 질의만 허용된 DB에서, 특정 조건의 결과 인원이 1명임을 확인하고 평균값으로 그 사람의 급여를 알아냈다. 이 위협과 대책의 연결로 가장 적절한 것은?
① 집성 – 데이터 집합 등급 상향 ② 추론 – 최소 질의 결과 집합 크기 제한 ③ SQL 인젝션 – PreparedStatement ④ 권한 상승 – REVOKE
정답: ②
- ② 맞음: 허용된 통계로 개별값을 유추 → 추론. 결과 집합이 너무 작으면 응답 거부.
- ① 틀림: 집성은 낮은 등급 정보를 단순히 모아 상위 의미를 얻는 것.
- ③④ 해당 없음.
Q5. DB 암호화 방식 중 애플리케이션 수정 없이 DBMS 커널 수준에서 데이터 블록을 저장할 때 자동으로 암호화하는 방식은?
① API 방식 ② 플러그인 방식 ③ TDE 방식 ④ 응용 프로그램 해시 방식
정답: ③
- ① 틀림: 앱 서버에서 암호화 → 소스 수정 필요.
- ② 틀림: DB에 모듈 설치, 질의 수정이 일부 필요할 수 있음.
- ③ 맞음: Transparent Data Encryption.
- ④ 일반적인 분류가 아님.
Q6. DB 접근제어 솔루션의 스니핑 방식에 대한 설명으로 옳은 것은?
① DB 서버에 에이전트를 설치한다 ② 모든 질의가 별도 프록시 서버를 반드시 경유한다 ③ 성능 영향은 적지만 실시간 차단이 어렵다 ④ DB 서버 로컬 접속까지 완벽히 감시한다
정답: ③
- ① 에이전트 방식. ② 게이트웨이 방식. ④ 스니핑은 네트워크 트래픽만 보므로 로컬 접속 감시 불가.
- ③ 맞음.
Day 5 · 전자상거래 · 개발 보안
5-1. 전자상거래 보안 요구사항
| 요구사항 | 의미 | 기술 |
|---|---|---|
| 기밀성 | 카드번호·주문 내용 노출 방지 | 암호화(SSL/TLS, 전자봉투) |
| 무결성 | 금액·주문 변조 방지 | 해시, MAC, 전자서명 |
| 인증 | 거래 상대가 진짜인가 | 인증서(PKI), 비밀번호, OTP |
| 부인방지 | 주문·지불 사실 부인 불가 | 전자서명 |
| 가용성 | 결제 서비스 지속 | 이중화, DDoS 대응 |
| 프라이버시 | 불필요한 정보 노출 최소 | SET 이중서명, 익명성 |
PKI·전자서명 기초(인증서 구조, CA·RA, CRL·OCSP)는 암호학 범위와 겹칩니다. 여기서는 "전자상거래에서 어떤 요소를 위해 쓰이는가"로 연결해 두세요: 전자서명 = 인증 + 무결성 + 부인방지, 전자봉투 = 대칭키를 수신자 공개키로 감싸 기밀성.
5-2. 전자지불 수단별 보안 요소
| 지불 수단 | 형태 | 주요 보안 요소 |
|---|---|---|
| 신용카드 기반 | SSL/TLS 결제창, SET, 3-D Secure | 카드정보 기밀성, 카드소지자 인증, 상점 인증 |
| 전자화폐 – IC카드형 | 카드 칩에 화폐 가치 저장 (예: Mondex) | 칩 위변조 방지(탬퍼 저항), 오프라인 결제 |
| 전자화폐 – 네트워크형 | 컴퓨터·서버에 화폐 정보 저장 (예: eCash) | 은닉서명으로 익명성, 이중 사용 검사 |
| 전자수표 | 전자서명된 수표 | 발행인 서명·은행 인증서, 이중 제시 방지 |
| 전자자금이체 | 계좌이체·인터넷뱅킹 | 인증서, OTP, 보안카드 |
| 소액결제(Micropayment) | 아주 적은 금액 다수 (Millicent, PayWord) | 저비용 처리 위해 해시 체인 등 경량 기법 |
전자화폐의 요건
| 요건 | 의미 |
|---|---|
| 익명성(프라이버시) | 사용 내역으로 사용자를 추적 불가 → 은닉서명(Blind Signature): 은행이 내용을 보지 않고 서명 |
| 이중 사용 방지 | 같은 화폐를 두 번 쓰지 못함 (디지털 데이터는 복사 쉬움) |
| 위조 불가(안전성) | 위조·변조 불가 |
| 양도성 | 다른 사람에게 이전 가능 |
| 분할성 | 액면을 나누어 사용 가능 |
| 오프라인성 | 결제 시 은행과 온라인 연결 없이 가능 |
| 독립성 | 물리적 위치·매체에 의존하지 않음 |
은닉서명: 사용자가 메시지를 가려서(blinding) 은행에 서명받고, 나중에 가림을 벗기면 은행의 유효한 서명이 남지만 은행은 어떤 화폐에 서명했는지 모름 → 익명성. 대신 이중 사용 시에는 신원이 드러나도록 설계하는 방식이 있음.
5-3. SET (Secure Electronic Transaction)
VISA·MasterCard가 1996년 공동 제정한 신용카드 결제 전용 보안 프로토콜. 모든 참여자가 인증서를 갖고, 상점은 카드번호를 볼 수 없게 설계됨.
참여자
| 참여자 | 역할 |
|---|---|
| 카드소지자(Cardholder) | 구매자, 전자지갑 SW 사용 |
| 상점(Merchant) | 판매자 |
| 발급사(Issuer) | 카드를 발급한 은행 |
| 매입사(Acquirer) | 상점의 거래 은행 |
| 지불 게이트웨이(Payment Gateway) | 매입사가 운영, 인터넷 SET 메시지 ↔ 기존 카드 결제망 변환, 승인 처리 |
| 인증기관(CA) | 모든 참여자에게 X.509 인증서 발급 (계층 구조) |
이중 서명(Dual Signature) 구성
목표: 상점은 주문정보(OI)만, 은행(지불 게이트웨이)은 지불정보(PI)만 보게 하면서도, 두 정보가 같은 거래로 연결되어 있음을 둘 다 검증하게 한다.
PI (지불정보: 카드번호 등) OI (주문정보: 상품·금액)
│ │
H(PI) H(OI)
│ │
PIMD ─────────────┬──────────────── OIMD
│ 연접(PIMD ‖ OIMD)
▼
H(PIMD ‖ OIMD) = POMD
│
카드소지자 개인키로 서명
▼
DS = E(KRc, POMD) ← 이중 서명
| 받는 쪽 | 받는 것 | 검증 방법 |
|---|---|---|
| 상점 | OI, PIMD, DS (+ 암호화된 PI 봉투는 그대로 게이트웨이로 전달) | H(OI)=OIMD 계산 → H(PIMD‖OIMD) 계산 → DS를 카드소지자 공개키로 풀어 비교 |
| 지불 게이트웨이 | PI(전자봉투로 암호화), OIMD, DS | H(PI)=PIMD 계산 → H(PIMD‖OIMD) 계산 → DS 검증 |
- 결과: 상점은 카드번호를 모름, 은행은 무엇을 샀는지 모름 → 프라이버시 + 연결성 + 부인방지.
- PI는 랜덤 세션키로 암호화하고, 세션키는 게이트웨이의 공개키로 암호화(전자봉투)해 상점이 열 수 없음.
SSL/TLS vs SET
| 구분 | SSL/TLS | SET |
|---|---|---|
| 목적 | 범용 통신 채널 보안 | 신용카드 결제 전용 |
| 계층 | 전송 계층 위(세션) | 응용 계층 |
| 인증 | 주로 서버만 인증(클라이언트 인증 선택) | 모든 참여자 인증서 |
| 상점이 카드번호 보나 | 본다(복호화 후 상점 서버에 존재) | 못 본다(이중서명·봉투) |
| 부인방지 | 제공하지 않음(채널 보호만) | 제공(전자서명) |
| 구현 | 브라우저 내장, 간단, 빠름 | 전자지갑 SW, 인증서 필요, 복잡·느림·비용 |
| 현황 | 현재 표준 | 거의 사용되지 않음 |
5-4. 무선 전자상거래: WAP · WTLS
WAP(Wireless Application Protocol)은 저성능 휴대 단말을 위한 무선 인터넷 프로토콜 스택(WAP 1.x).
| 계층 | WAP 프로토콜 | 대응되는 인터넷 |
|---|---|---|
| 응용 | WAE (WML, WMLScript) | HTML, JavaScript |
| 세션 | WSP | HTTP |
| 트랜잭션 | WTP | (TCP 일부 기능) |
| 보안 | WTLS | SSL/TLS |
| 전송 | WDP | UDP |
[휴대 단말] ──WTLS(무선 구간 암호)──▶ [WAP 게이트웨이] ──SSL/TLS(유선 구간)──▶ [웹 서버]
▲
여기서 WTLS 복호화 → SSL 재암호화
잠깐 평문 상태 = "WAP Gap" (종단간 보안 단절)
- WAP Gap: 게이트웨이에서 데이터가 평문으로 노출되는 구간 → 게이트웨이를 서비스 제공자(은행) 내부에 두거나, WAP 2.0처럼 TLS 종단간(end-to-end) 사용으로 해결.
- WTLS 특징: 데이터그램(UDP) 환경에서도 동작, 경량화, 무선 환경 최적화. WIM(무선 식별 모듈)에 키 저장.
5-5. Secure SDLC (보안 개발 생명주기)
왜 필요한가
취약점을 운영 단계에서 고치는 비용은 설계 단계보다 훨씬 큽니다. 그래서 요구사항·설계 단계부터 보안을 넣는 것(Shift Left)이 핵심 사상입니다. 국내에서는 행정기관 등 공공 정보화사업에 SW 개발보안 적용이 2012년부터 단계적으로 의무화되었습니다.
flowchart LR
A[요구사항
보안 요구사항 정의] --> B[설계
위협 모델링
보안 설계 검토]
B --> C[구현
시큐어 코딩
SAST·코드리뷰]
C --> D[테스트
DAST·퍼징
모의해킹]
D --> E[배포
보안 설정 점검
최종 보안 검토]
E --> F[운영·유지보수
패치·모니터링
사고 대응]
F -.피드백.-> A방법론 비교
| 방법론 | 주체 | 핵심 |
|---|---|---|
| MS SDL | Microsoft | 교육 → 요구사항 → 설계 → 구현 → 검증 → 릴리스 → 대응. 위협 모델링(STRIDE), 금지 API, 최종 보안 검토(FSR) |
| CLASP | OWASP | 역할(Role) 기반 보안 활동 정의. 5가지 관점(개념, 역할 기반, 활동 평가, 활동 구현, 취약성 관점). 기존 개발 프로세스에 추가 적용하기 쉬움 |
| Seven Touchpoints | Gary McGraw (Cigital) | 개발 산출물마다 7가지 접점 보안 활동: 코드 검토, 아키텍처 위험 분석, 침투 테스트, 위험 기반 보안 테스트, 오용 사례(Abuse case), 보안 요구사항, 보안 운영. 공격자·방어자 관점 병행 |
- STRIDE(위협 분류): Spoofing(위장→인증), Tampering(변조→무결성), Repudiation(부인→부인방지), Information Disclosure(정보 노출→기밀성), Denial of Service(→가용성), Elevation of Privilege(권한 상승→인가)
5-6. 시큐어 코딩 7대 유형 (행정안전부 SW 개발보안 가이드, 구현 단계)
| 유형 | 의미 | 대표 약점(예) |
|---|---|---|
| 1. 입력데이터 검증 및 표현 | 입력값 검증 부재·부적절 | SQL 삽입, 코드 삽입, 경로 조작 및 자원 삽입, XSS, 운영체제 명령어 삽입, 위험한 형식 파일 업로드, 신뢰되지 않는 URL 주소로 자동접속 연결, 부적절한 XML 외부개체 참조(XXE), XML 삽입, LDAP 삽입, CSRF, SSRF, HTTP 응답분할, 정수형 오버플로우, 보안기능 결정에 사용되는 부적절한 입력값, 메모리 버퍼 오버플로우, 포맷 스트링 삽입 |
| 2. 보안기능 | 인증·접근제어·암호화·권한 관리의 부적절한 구현 | 적절한 인증 없는 중요기능 허용, 부적절한 인가, 중요 자원 잘못된 권한 설정, 취약한 암호화 알고리즘, 암호화되지 않은 중요정보, 하드코드된 중요정보, 충분하지 않은 키 길이, 적절하지 않은 난수 값, 취약한 비밀번호 허용, 부적절한 전자서명·인증서 검증, 쿠키를 통한 정보노출, 주석문 안 시스템 주요정보, 솔트 없는 일방향 해시, 무결성 검사 없는 코드 다운로드, 반복된 인증시도 제한 기능 부재 |
| 3. 시간 및 상태 | 동시·병렬 처리 시 시간·상태 관리 부적절 | 경쟁조건: 검사 시점과 사용 시점(TOCTOU), 종료되지 않는 반복문 또는 재귀 함수 |
| 4. 에러처리 | 오류를 처리하지 않거나 오류 정보에 중요정보 포함 | 오류 메시지 정보노출, 오류상황 대응 부재, 부적절한 예외 처리 |
| 5. 코드오류 | 개발자가 흔히 만드는 코딩 실수 | Null Pointer 역참조, 부적절한 자원 해제, 해제된 자원 사용, 초기화되지 않은 변수 사용, 신뢰할 수 없는 데이터의 역직렬화 |
| 6. 캡슐화 | 중요 데이터·기능을 불충분하게 캡슐화 | 잘못된 세션에 의한 데이터 정보노출, 제거되지 않고 남은 디버그 코드, Public 메소드로부터 반환된 Private 배열, Private 배열에 Public 데이터 할당 |
| 7. API 오용 | 의도와 다르게 API 사용, 보안 취약 API 사용 | DNS lookup에 의존한 보안결정, 취약한 API 사용 |
암기 팁: "입보시에코캡A" (입력·보안기능·시간·에러·코드오류·캡슐화·API)
코드 예 – 에러처리 / 보안기능:
// ❌ 에러처리: 스택트레이스를 사용자에게 노출
catch (SQLException e) { e.printStackTrace(response.getWriter()); }
// ✅ 사용자에게는 일반 메시지, 상세는 서버 로그로
catch (SQLException e) { log.error("DB 오류", e); response.sendError(500); }
// ❌ 보안기능: 하드코드된 비밀번호, 예측 가능한 난수
String dbPw = "P@ssw0rd!";
int token = new java.util.Random().nextInt();
// ✅ 외부 보안 저장소에서 로딩, 암호학적 난수
String dbPw = secretStore.get("db.password");
byte[] t = new byte[32]; new java.security.SecureRandom().nextBytes(t);
설계 단계 보안 요구항목 (참고)
행안부 가이드는 설계 단계 보안 요구항목도 정의합니다(입력데이터 검증, 보안기능, 에러처리, 세션통제 영역). 구현 단계 7대 유형과 구분: 설계 단계는 "무엇을 보안 요구사항으로 정할지", 구현 단계는 "코드에서 어떤 약점을 피할지".
5-7. 개발 보안 도구
| 도구 | 방식 | 시점 | 장점 | 한계 |
|---|---|---|---|---|
| SAST (정적 분석) | 소스코드·바이트코드를 실행하지 않고 분석 (화이트박스) | 구현 단계(초기) | 취약 **코드 위치(줄)**까지 제시, 조기 발견 | 오탐 많음, 실행 환경·설정 문제는 못 봄 |
| DAST (동적 분석) | 실행 중인 앱에 외부에서 요청을 보내 반응 관찰 (블랙박스) | 테스트·운영 | 실제 동작 기반, 언어 무관, 설정 오류도 발견 | 코드 위치 모름, 커버리지 한계, 늦은 시점 |
| IAST (대화형) | 앱 내부에 에이전트(계측) + 테스트 실행 중 데이터 흐름 관찰 | 테스트 | SAST+DAST 장점, 오탐 적음 | 에이전트 언어 종속, 성능 영향 |
| RASP | 운영 중인 앱 내부에서 실시간 공격 차단 | 운영 | 문맥 기반 차단 | 성능, 종속성 |
| SCA | 오픈소스·서드파티 구성요소의 알려진 취약점(CVE)·라이선스 점검, SBOM | 전 단계 | 오래된 구성요소 위험 대응 | 자체 코드 취약점은 못 봄 |
| 퍼징(Fuzzing) | 비정상·무작위·변형 입력을 대량 주입해 크래시·예외 유발 | 테스트 | 미지의 취약점(버퍼 오버플로우 등) 발견 | 결과 분석 부담 |
| 코드 리뷰 | 사람이 직접 검토 | 구현 | 논리 결함 발견 | 시간·인력 |
| 모의해킹 | 공격자 관점 수동 테스트 | 배포 전·운영 | 실제 위험 확인 | 비용, 특정 시점 |
- SET에서 상점은 PIMD를, 게이트웨이는 OIMD를 받는다(상대 정보는 해시만). 원문을 받는다고 하면 틀림.
- SET 이중서명은 카드소지자의 개인키로 서명한다. 상점 키가 아님.
- SSL은 부인방지를 제공하지 않는다, SET은 제공. SSL에서는 상점이 카드번호를 볼 수 있다.
- 전자화폐 익명성의 핵심 기술은 은닉서명(이중 서명 아님).
- WTLS는 WAP의 보안 계층이며 SSL/TLS에 대응. WAP Gap은 게이트웨이에서 발생.
- CLASP는 OWASP, Touchpoints는 McGraw, SDL은 Microsoft. STRIDE는 MS의 위협 모델링 분류.
- 오류 메시지 노출 → 에러처리, 디버그 코드 잔존 → 캡슐화, 경쟁조건 → 시간 및 상태, 역직렬화 → 코드오류, 하드코드 비밀번호·취약 난수 → 보안기능, CSRF·SSRF → 입력데이터 검증 및 표현.
- SAST는 실행하지 않는다, DAST는 실행한다. 퍼징은 동적 테스트의 일종.
- SET 참여자, 이중서명 구성 순서(해시 → 연접 → 해시 → 개인키 서명), 상점·게이트웨이가 받는 정보.
- SSL vs SET 비교표에서 틀린 것 고르기.
- 전자화폐 요건, 은닉서명의 목적.
- 7대 유형에 약점 분류하기(가장 빈출), Secure SDLC 방법론 주체 연결.
- SAST/DAST/IAST/SCA 정의 매칭.
확인 문제 (Day 5)
Q1. SET의 이중 서명에 대한 설명으로 옳지 않은 것은?
① 주문정보와 지불정보의 해시값을 연접하여 다시 해시한다 ② 카드소지자의 개인키로 서명한다 ③ 상점은 지불정보 원문과 주문정보 원문을 모두 받아 검증한다 ④ 지불 게이트웨이는 주문정보의 해시값만 받는다
정답: ③
- ③ 틀림(정답): 상점은 **주문정보(OI) 원문 + PIMD(지불정보 해시)**만 받는다. 카드번호를 볼 수 없게 하는 것이 SET의 목적.
- ①②④ 옳음.
Q2. SSL/TLS 기반 결제와 비교한 SET의 특징으로 옳은 것은?
① 서버만 인증한다 ② 상점이 카드번호를 확인할 수 있다 ③ 전자서명으로 부인방지를 제공한다 ④ 구현이 간단하여 현재 가장 널리 쓰인다
정답: ③
- ①② SSL의 특징.
- ③ 맞음.
- ④ 틀림: SET은 복잡·고비용으로 거의 쓰이지 않음.
Q3. 전자화폐에서 은행이 화폐의 내용을 알지 못한 채 서명하게 하여 사용자의 익명성을 보장하는 기술은?
① 이중 서명 ② 은닉 서명 ③ 그룹 서명 ④ 부인방지 서명
정답: ②
- ② 맞음: Blind Signature.
- ① SET의 OI·PI 연결. ③ 그룹 구성원이 익명으로 서명하는 기법(전자화폐 익명성의 표준 답은 은닉서명). ④ 서명자 협조 없이는 검증할 수 없는 서명 — 익명성과 무관.
Q4. 행정안전부 시큐어 코딩 가이드의 보안약점 유형 분류로 옳지 않은 것은?
① 오류 메시지 정보노출 – 에러처리 ② 제거되지 않고 남은 디버그 코드 – 캡슐화 ③ 경쟁조건(TOCTOU) – 시간 및 상태 ④ 하드코드된 중요정보 – API 오용
정답: ④
- ④ 틀림(정답): 하드코드된 중요정보는 보안기능. API 오용은 DNS lookup 의존 보안결정, 취약한 API 사용.
- ①②③ 옳음.
Q5. OWASP에서 제안한, 역할(Role) 기반으로 보안 활동을 정의하여 기존 개발 프로세스에 적용하기 쉬운 방법론은?
① MS SDL ② CLASP ③ Seven Touchpoints ④ STRIDE
정답: ②
- ① Microsoft. ③ McGraw의 7가지 접점. ④ MS의 위협 분류 모델(방법론 자체가 아님).
- ② 맞음.
Q6. 실행 중인 웹 애플리케이션에 외부에서 공격 요청을 보내 응답을 관찰하는 블랙박스 방식의 분석 도구는?
① SAST ② SCA ③ DAST ④ 코드 리뷰
정답: ③
- ① 실행 없이 소스 분석. ② 오픈소스 구성요소 점검. ④ 사람이 소스를 읽음.
- ③ 맞음.
Day 6 · 2027 신규 · 실기 연결: REST API · OAuth 2.0 · JWT
6-1. REST API 보안 기본
REST API는 **자원(URI) + 행위(HTTP 메서드) + 표현(JSON)**으로 구성됩니다. 웹 페이지와 달리 화면 없이 데이터를 직접 주고받으므로, 화면에서 버튼을 숨기는 식의 "UI 통제"는 의미가 없고 서버가 매 요청마다 인증·인가를 검사해야 합니다.
| 메서드 | 의미 | 예 |
|---|---|---|
| GET | 조회 | GET /api/orders/1001 |
| POST | 생성 | POST /api/orders |
| PUT / PATCH | 전체 / 부분 수정 | PATCH /api/users/7 |
| DELETE | 삭제 | DELETE /api/orders/1001 |
- 무상태(Stateless): 서버가 세션을 저장하지 않는 경우가 많음 → 매 요청에 토큰(
Authorization: Bearer <토큰>)을 실어 인증. - 상태 코드 구분: 401 Unauthorized = 인증 안 됨(누구인지 모름), 403 Forbidden = 인가 거부(누구인지는 알지만 권한 없음), 429 Too Many Requests = 요청 한도 초과.
요청/응답 예:
GET /api/v2/orders/1001 HTTP/1.1
Host: api.shop.example
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3Ii...
Accept: application/json
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
X-Content-Type-Options: nosniff
{"orderId":1001,"status":"SHIPPED","items":[{"sku":"A-1","qty":2}]}
REST API 공통 보안 수칙:
- HTTPS 필수, API 키·토큰은 URL 쿼리에 넣지 말 것(로그·Referer로 유출) → 헤더 사용
- 객체마다 소유자 검사(BOLA 방지), 기능마다 역할 검사(BFLA 방지)
- 입력은 스키마 검증(타입·길이·범위), 응답은 필요한 필드만
- Rate Limiting·페이지 크기 제한·요청 크기 제한
- API 게이트웨이로 인증·한도·로깅 일원화
- CORS 최소 허용 (
Access-Control-Allow-Origin: *과 자격증명 허용을 함께 쓰지 말 것) - API 버전·엔드포인트 목록(인벤토리) 관리, 구버전 폐기
6-2. OWASP API Security Top 10 (2023)
| 순위 | 항목 | 설명 | 예 | 대책 |
|---|---|---|---|---|
| API1 | BOLA (Broken Object Level Authorization) | 객체 ID만 바꾸면 남의 객체 접근 | GET /api/orders/1001 → 1002로 바꿔 타인 주문 조회 |
요청자 = 객체 소유자인지 매 요청 검사, 추측 어려운 ID(UUID)는 보조 |
| API2 | Broken Authentication | 인증 메커니즘 결함 | 토큰 서명 미검증, 로그인 무차별 대입 허용, 약한 비밀번호 재설정 | 표준 인증, 시도 제한, MFA, 토큰 검증 |
| API3 | BOPLA (Broken Object Property Level Authorization) | 속성(필드) 단위 인가 실패 = 과도한 데이터 노출 + 대량 할당(Mass Assignment) | 응답에 passwordHash 포함 / 요청 본문에 "isAdmin":true 넣었더니 반영 |
응답 필드 화이트리스트, 수정 가능 필드만 바인딩 |
| API4 | Unrestricted Resource Consumption | 요청 수·크기·비용 제한 없음 | ?limit=1000000, SMS 발송 API 무한 호출로 비용 폭탄 |
Rate Limit, 페이지 크기·업로드 크기·타임아웃 제한, 비용 한도 |
| API5 | BFLA (Broken Function Level Authorization) | 기능(엔드포인트) 단위 인가 실패 | 일반 사용자가 DELETE /api/admin/users/7 호출 성공 |
역할 기반 기본 거부, 관리자 API 분리 |
| API6 | Unrestricted Access to Sensitive Business Flows | 정상 기능이지만 자동화로 대량 악용되면 피해 | 한정판 상품 봇 매점, 쿠폰 대량 발급, 예약 선점 | 봇 탐지, 기기 핑거프린팅, 사람 확인(CAPTCHA), 흐름별 한도 |
| API7 | SSRF | API가 사용자 제공 URL을 서버에서 요청 | 웹훅 URL에 내부 주소 등록 | URL 화이트리스트, 내부망 차단 |
| API8 | Security Misconfiguration | 잘못된 설정 | 상세 오류·스택 트레이스, CORS 과허용, HTTPS 미적용, 불필요 메서드 | 하드닝, 자동 점검 |
| API9 | Improper Inventory Management | API 목록·버전 관리 부실 | 보안 패치 안 된 /api/v1이 계속 열려 있음, 테스트용 API 운영 노출 |
API 인벤토리·문서화, 구버전 폐기, 환경 분리 |
| API10 | Unsafe Consumption of APIs | 외부(서드파티) API 응답을 과신 | 연동한 외부 API 응답값을 검증 없이 SQL에 사용, 리다이렉트 무조건 추종 | 외부 데이터도 검증, TLS, 리다이렉트 제한 |
BOLA vs BFLA vs BOPLA 한눈에:
BOLA : "남의 '물건'을 봤다" /orders/1002 (객체 단위)
BOPLA : "물건의 '숨긴 칸'을 봤다/고쳤다" "isAdmin":true (속성 단위)
BFLA : "내가 못 쓰는 '기능'을 썼다" /admin/... (기능 단위)
취약 코드 vs 수정 코드 (BOLA):
// ❌ ID만으로 조회 → BOLA
@GetMapping("/api/orders/{id}")
public Order get(@PathVariable Long id) {
return orderRepo.findById(id).orElseThrow();
}
// ✅ 로그인 사용자 소유인지 확인
@GetMapping("/api/orders/{id}")
public Order get(@PathVariable Long id, @AuthenticationPrincipal User me) {
Order o = orderRepo.findById(id).orElseThrow();
if (!o.getOwnerId().equals(me.getId())) throw new AccessDeniedException("403");
return o;
}
6-3. OAuth 2.0
OAuth 2.0은 인가(Authorization) 위임 프레임워크입니다. 사용자가 비밀번호를 제3자 앱에 주지 않고, "이 앱이 내 사진을 읽는 것만 허락" 같은 **제한된 권한(Scope)**을 Access Token으로 위임합니다.
| 역할 | 의미 | 예 |
|---|---|---|
| Resource Owner | 자원 소유자(사용자) | 나 |
| Client | 자원을 쓰려는 애플리케이션 | 사진 인화 앱 |
| Authorization Server | 사용자 인증·동의 후 토큰 발급 | 구글·카카오 로그인 서버 |
| Resource Server | 토큰을 검사하고 자원 제공 | 사진 API 서버 |
Authorization Code + PKCE 흐름 (권장):
sequenceDiagram
participant U as 사용자 브라우저
participant C as 클라이언트 앱
participant AS as 인가 서버
participant RS as 자원 서버
C->>C: code_verifier 생성, code_challenge = 해시값
C->>U: 인가 서버로 리다이렉트 (client_id, scope, state, code_challenge)
U->>AS: 로그인 및 권한 동의
AS-->>U: redirect_uri 로 리다이렉트 (code, state)
U->>C: code, state 전달
C->>C: state 값 일치 확인 (CSRF 방지)
C->>AS: code + code_verifier 로 토큰 요청 (백채널)
AS->>AS: code_verifier 해시 = code_challenge 확인
AS-->>C: Access Token (+ Refresh Token)
C->>RS: API 호출 Authorization Bearer 토큰
RS-->>C: 자원| Grant 유형 | 용도 | 비고 |
|---|---|---|
| Authorization Code (+PKCE) | 웹·모바일·SPA | 권장 |
| Client Credentials | 서버 간(사용자 없음) | |
| Device Code | TV 등 입력 제한 기기 | |
| Refresh Token | Access Token 재발급 | |
| Implicit | 브라우저에 토큰 직접 전달 | 폐기 권고(토큰 URL 노출) |
| Resource Owner Password | 앱이 사용자 비밀번호 직접 받음 | 폐기 권고 |
OAuth 보안 포인트:
state파라미터: 인가 응답 위조(CSRF) 방지- PKCE: 인가 코드가 탈취되어도
code_verifier없이는 토큰 교환 불가 (모바일·SPA 필수) - redirect_uri 정확히 일치 검증 (느슨하면 코드가 공격자 사이트로 유출 → 오픈 리다이렉트와 결합)
- Scope 최소화, Access Token 짧은 수명, Refresh Token 회전·안전 저장
- OAuth는 인가용. **인증(로그인)**은 그 위의 **OpenID Connect(OIDC)**가 **ID Token(JWT)**으로 제공
6-4. JWT (JSON Web Token)
구조
xxxxx.yyyyy.zzzzz
│ │ └─ Signature = 서명( Base64URL(Header) + "." + Base64URL(Payload), 키 )
│ └──────── Payload (클레임: 사용자·권한·만료)
└─────────────── Header (알고리즘·타입)
각 부분은 Base64URL 인코딩 → 누구나 디코딩해서 읽을 수 있음 (암호화 아님!)
// Header
{ "alg": "RS256", "typ": "JWT", "kid": "2027-key-1" }
// Payload
{
"iss": "https://auth.shop.example", // 발급자
"sub": "7", // 주체(사용자 ID)
"aud": "shop-api", // 대상(이 토큰을 받을 서비스)
"iat": 1798771200, // 발급 시각
"exp": 1798772100, // 만료 시각 (15분)
"role": "user",
"jti": "a9f3c1e0" // 토큰 고유 ID (재사용·폐기 관리)
}
| 구분 | 설명 |
|---|---|
| JWS | 서명된 JWT (일반적인 JWT) → 무결성·출처 인증, 내용은 공개 |
| JWE | 암호화된 JWT → 기밀성 |
| HS256 | HMAC + 공유 비밀키 (발급자=검증자 같은 키) |
| RS256/ES256 | 개인키로 서명, 공개키로 검증 (여러 서비스가 검증할 때 유리) |
JWT 공격과 대응
| 공격·실수 | 내용 | 대응 |
|---|---|---|
alg: none |
헤더를 none으로 바꾸고 서명 제거 → 검증 생략 라이브러리 악용 |
none 거부, 허용 알고리즘 고정 |
| 알고리즘 혼동 | RS256 서버에 HS256 토큰을 보내, 공개키를 HMAC 비밀키로 쓰게 함 |
서버가 기대 알고리즘 명시 검증 |
| 약한 HMAC 비밀키 | 오프라인 무차별 대입으로 키 추측 → 토큰 위조 | 충분히 긴 무작위 키 |
| 민감정보 Payload | Base64URL이라 누구나 읽음 | 비밀번호·주민번호 등 넣지 않기 (필요 시 JWE) |
| 만료 없음 | 탈취 토큰 영구 사용 | exp 짧게 + Refresh Token |
| 폐기 어려움 | 무상태라 로그아웃해도 유효 | 짧은 수명, jti 차단 목록 |
aud·iss 미검증 |
다른 서비스용 토큰 재사용 | 발급자·대상 검증 |
| 저장 위치 | localStorage는 XSS에 노출 | HttpOnly·Secure 쿠키(+CSRF 대책) 또는 메모리 |
kid 조작 |
키 ID로 경로·SQL 조작 | kid 값 검증 |
- JWT는 기본적으로 암호화가 아니라 서명이다. Payload는 Base64URL 디코딩만으로 읽힌다.
- OAuth 2.0은 인가 프레임워크. "OAuth = 인증 프로토콜"은 엄밀히 틀림 → 인증은 OIDC.
- 401 = 인증 실패, 403 = 인가 실패.
- BOLA(객체)·BFLA(기능)·BOPLA(속성) 구분. Mass Assignment와 과도한 데이터 노출은 2023판에서 API3 BOPLA로 통합.
- API9 부적절한 자산(인벤토리) 관리 = 구버전·테스트 API 방치. API10은 외부 API를 과신하는 것.
- Implicit Grant는 폐기 권고, SPA·모바일도 Authorization Code + PKCE.
- URL의 ID를 바꿔 타인 정보를 본 시나리오 → BOLA와 대책 서술.
- JWT 세 부분 이름·역할,
alg:none공격, 권장 검증 항목(서명·exp·iss·aud). - OAuth 4가지 역할,
state·PKCE·redirect_uri 검증 목적. - API 대응책 서술: 객체 수준 권한 검사, Rate Limiting, API 게이트웨이, 응답 필드 최소화, 인벤토리 관리.
확인 문제 (Day 6)
Q1. 사용자가 GET /api/users/120/profile 요청의 숫자를 121로 바꾸자 다른 사용자의 프로필이 반환되었다. OWASP API Security Top 10 (2023)에서 해당하는 항목은?
① API1 BOLA ② API3 BOPLA ③ API5 BFLA ④ API9 부적절한 인벤토리 관리
정답: ①
- ① 맞음: 객체 ID 조작으로 남의 객체 접근.
- ② 속성(필드) 단위 문제. ③ 기능(관리자 API) 단위 문제. ④ 구버전·미관리 API.
Q2. 회원정보 수정 API 요청 본문에 "role":"admin"을 추가했더니 권한이 변경되었다. 해당 취약점과 대책은?
① BFLA – 관리자 API 분리 ② BOPLA(Mass Assignment) – 수정 가능한 필드만 화이트리스트로 바인딩 ③ SSRF – URL 검증 ④ 무제한 자원 소비 – Rate Limiting
정답: ②
- ② 맞음: 클라이언트가 보낸 속성을 객체에 일괄 바인딩해서 생긴 속성 수준 인가 실패.
- ① 기능 엔드포인트 자체의 인가 문제가 아님. ③④ 무관.
Q3. JWT에 대한 설명으로 옳지 않은 것은?
① Header, Payload, Signature 세 부분이 점(.)으로 구분된다 ② Payload는 Base64URL로 암호화되어 있어 비밀번호를 넣어도 안전하다 ③ exp 클레임으로 만료 시간을 지정한다 ④ 서버는 alg: none 토큰을 거부해야 한다
정답: ②
- ② 틀림(정답): Base64URL은 인코딩이지 암호화가 아님. 누구나 디코딩 가능.
- ①③④ 옳음.
Q4. OAuth 2.0 Authorization Code 흐름에서 state 파라미터의 주된 목적은?
① 토큰 만료 시간 지정 ② 인가 응답 위조(CSRF) 방지 ③ 접근 범위 제한 ④ 클라이언트 비밀번호 전달
정답: ②
- ② 맞음: 요청 때 보낸 state와 돌아온 state를 비교해 공격자가 끼워넣은 응답을 거부.
- ①
exp/expires_in. ③scope. ④ 해당 없음.
Q5. 다음 중 OAuth 2.0의 구성 역할이 아닌 것은?
① Resource Owner ② Authorization Server ③ Resource Server ④ Certificate Revocation Server
정답: ④
- ①②③ 및 Client가 OAuth 2.0의 4가지 역할.
- ④ 그런 역할은 없음(인증서 폐기는 PKI의 CRL/OCSP).
Day 7 · 주간 정리
7-1. 한 장 요약
서비스별 "운영 + 공격·대응" 요약
| 서비스 | 개요·운영 핵심 | 대표 공격 | 대표 대응 |
|---|---|---|---|
| Web/App | HTTP, 세션·쿠키, Apache/IIS/Tomcat 하드닝, 로그 | SQLi, XSS, CSRF, SSRF, 업로드·웹셸, 경로조작, 인증·세션 결함 | PreparedStatement, 출력 인코딩·CSP, CSRF 토큰·SameSite, 화이트리스트, WAF, 시큐어 코딩 |
| FTP | 21 제어 / 20 데이터, Active(서버→클라) vs Passive(클라→서버) | Bounce(PORT), Anonymous, 평문 스니핑, TFTP 무인증 | ftpusers(거부 목록), vsftpd 설정, chroot, SFTP/FTPS |
| 메일 | MUA→MTA→MDA→MUA, SMTP 25/587, POP3 110, IMAP 143 | 오픈 릴레이, EXPN/VRFY, 메일 폭탄, 스팸·스푸핑 | 릴레이 제한, 명령 비활성화, SPF/DKIM/DMARC, RBL, PGP·S/MIME |
| DNS | 레코드, 재귀(클→로컬)·반복(로컬→권한), UDP/TCP 53 | 캐시 포이즈닝·카민스키, 증폭 DDoS, 터널링, 존 전송 유출, 파밍 | DNSSEC, 포트 랜덤화, allow-transfer/recursion 제한, 버전 숨김, RRL |
| DB | GRANT/REVOKE, ROLE, VIEW, 감사 | SQLi, 추론, 집성, 과도 권한 | 최소 권한, 다중 인스턴스화, 암호화(API/플러그인/TDE), 접근제어 솔루션 |
| 전자상거래 | 지불 수단, PKI·전자서명 | 카드정보 노출, 부인 | SET 이중서명, SSL/TLS, 은닉서명 |
| API | REST, 토큰, OAuth, JWT | BOLA, BOPLA, BFLA, 자원 소비 | 객체 권한 검사, 필드 화이트리스트, Rate Limit, 게이트웨이 |
헷갈리는 쌍 정리
| 쌍 | 구분 포인트 |
|---|---|
| XSS vs CSRF | XSS = 피해자 브라우저에서 스크립트 실행 / CSRF = 피해자 권한으로 요청만 위조 |
| CSRF vs SSRF | CSRF = 브라우저가 요청 / SSRF = 서버가 요청 |
| Stored vs Reflected vs DOM | 저장됨 / 즉시 반사 / 클라이언트 JS 처리 |
| Active vs Passive FTP | 서버가 20번에서 접속 / 클라이언트가 서버 임의 포트로 접속 |
| SFTP vs FTPS | SSH 기반(22) / FTP+TLS(21·990) |
| POP3 vs IMAP | 다운로드 후 삭제 / 서버 보관·동기화 |
| PGP vs S/MIME | 신뢰의 웹 / X.509 PKI |
| SPF vs DKIM vs DMARC | IP / 서명 / 정책·정렬·보고 |
| 재귀 vs 반복 | 클라이언트→로컬 / 로컬→루트·TLD·권한 |
| 추론 vs 집성 | 유추 / 수집 |
| API vs 플러그인 vs TDE | 앱에서 / DB 모듈 / DBMS 커널 |
| 게이트웨이 vs 에이전트 vs 스니핑 | 경유 프록시 / DB 서버 설치 / 미러링 감시 |
| SSL vs SET | 범용·서버인증·부인방지X / 카드 전용·전원 인증서·부인방지O |
| SAST vs DAST | 실행 안 함·소스 / 실행 중·외부 |
| BOLA vs BFLA vs BOPLA | 객체 / 기능 / 속성 |
| 401 vs 403 | 인증 실패 / 인가 실패 |
7-2. 미니 모의고사 (20문항)
제한 시간 25분. 다 풀고 나서 아래 접힌 정답을 여세요.
1. 다음 중 SQL 인젝션의 근본적인 대응책으로 가장 적절한 것은?
① 오류 메시지 숨김 ② 바인딩 변수를 사용하는 파라미터화 쿼리 ③ WAF 도입 ④ 클라이언트 측 입력 길이 제한
2. 공격자가 # 뒤에 스크립트를 넣은 링크를 배포했고, 서버 로그에는 해당 스크립트 흔적이 남지 않았다. 가장 가능성이 높은 XSS 유형은?
① Stored ② Reflected ③ DOM 기반 ④ Blind
3. HttpOnly 쿠키 속성의 효과로 옳은 것은?
① HTTPS에서만 쿠키 전송 ② 자바스크립트에서 쿠키 접근 차단 ③ 다른 사이트에서 시작된 요청에 쿠키 미전송 ④ 쿠키 값 암호화
4. OWASP Top 10 2021에서 새로 추가된 항목이 아닌 것은?
① 안전하지 않은 설계 ② 소프트웨어 및 데이터 무결성 실패 ③ SSRF ④ 인젝션
5. Apache에서 .htaccess 파일에 의한 설정 변경을 막는 지시어는?
① Options -Indexes ② AllowOverride None ③ ServerSignature Off ④ LimitRequestBody 0
6. 웹 로그 "GET /dl.php?f=..%2F..%2Fetc%2Fshadow HTTP/1.1" 200에서 의심되는 공격은?
① SQL 인젝션 ② 경로 조작 ③ CSRF ④ HTTP 응답 분할
7. FTP Active 모드에서 데이터 연결을 시작하는 쪽과 포트는?
① 클라이언트, 서버 21번 ② 서버, 서버 20번 ③ 클라이언트, 서버 임의 포트 ④ 서버, 서버 21번
8. 인증 없이 UDP 69번 포트를 사용하여 파일을 전송하는 프로토콜은?
① SFTP ② FTPS ③ TFTP ④ SCP
9. 메일을 서버에 보관한 채 여러 기기에서 동기화하여 읽는 데 적합한 프로토콜은?
① SMTP ② POP3 ③ IMAP ④ MIME
10. S/MIME에 대한 설명으로 옳은 것은?
① 신뢰의 웹 모델을 사용한다 ② X.509 인증서 기반 PKI를 사용한다 ③ 메일 서버 간 릴레이를 제한하는 기술이다 ④ DNS TXT 레코드로 발송 IP를 검증한다
11. DMARC 레코드 p=quarantine의 의미는?
① 아무 조치 없이 보고만 한다 ② 인증 실패 메일을 격리(스팸함)한다 ③ 인증 실패 메일을 거부한다 ④ 모든 메일을 허용한다
12. 카민스키 DNS 공격의 특징으로 옳은 것은?
① 존 전송을 이용해 내부 호스트 목록을 얻는다 ② 존재하지 않는 서브도메인 질의를 반복하며 위조 NS 정보를 주입한다 ③ DNS 질의에 데이터를 숨겨 유출한다 ④ 출발지 IP를 위조해 큰 응답을 피해자에게 보낸다
13. DNS 증폭 공격을 완화하는 조치로 가장 적절한 것은?
① 외부 사용자에 대한 재귀 질의 제한 ② MX 레코드 삭제 ③ TTL을 매우 길게 설정 ④ CNAME 사용 금지
14. 다단계 보안 DB에서 동일 기본키에 대해 보안 등급별로 다른 튜플을 유지하는 기법은?
① 셀 억제 ② 다중 인스턴스화 ③ 뷰 ④ 집성
15. DB 암호화 방식 중 DB 종류와 무관하게 적용 가능하지만 애플리케이션 소스 수정이 많이 필요한 방식은?
① API 방식 ② 플러그인 방식 ③ TDE ④ 파일 암호화
16. SET에서 지불 게이트웨이가 이중 서명을 검증하기 위해 받는 정보로 옳은 것은?
① OI, PIMD, DS ② PI, OIMD, DS ③ OI, PI, DS ④ PIMD, OIMD
17. WAP 환경에서 WTLS와 SSL 사이 변환이 일어나는 게이트웨이에서 데이터가 평문으로 노출되는 문제는?
① WAP Gap ② Air Gap ③ Replay Gap ④ TLS Downgrade
18. 행안부 시큐어 코딩 7대 유형 중 "신뢰할 수 없는 데이터의 역직렬화"가 속하는 유형은?
① 입력데이터 검증 및 표현 ② 보안기능 ③ 코드오류 ④ 캡슐화
19. 오픈소스 라이브러리의 알려진 취약점과 라이선스를 점검하는 도구는?
① SAST ② DAST ③ SCA ④ RASP
20. OWASP API Security Top 10 (2023)에서 "보안 패치가 적용되지 않은 구버전 API가 운영 환경에 계속 노출된 상태"에 해당하는 항목은?
① API2 Broken Authentication ② API6 민감한 비즈니스 흐름에 대한 무제한 접근 ③ API9 Improper Inventory Management ④ API10 Unsafe Consumption of APIs
| 번호 | 정답 | 해설 |
|---|---|---|
| 1 | ② | 쿼리 구조와 데이터를 분리하는 것이 근본. ①③④는 보조 |
| 2 | ③ | # 뒤(fragment)는 서버로 전송되지 않음 → 클라이언트 JS 처리 = DOM XSS |
| 3 | ② | ①은 Secure, ③은 SameSite |
| 4 | ④ | 인젝션은 기존 항목(2017 A1). 신규는 ①②③ |
| 5 | ② | ① 리스팅, ③ 오류 페이지 서명, ④ 본문 크기(0은 무제한) |
| 6 | ② | ..%2F = ../ → 경로 조작으로 shadow 파일 접근 시도 |
| 7 | ② | Active: 서버가 20번 포트에서 클라이언트로 연결 |
| 8 | ③ | TFTP = UDP 69, 인증 없음 |
| 9 | ③ | IMAP은 서버 보관. POP3는 기본적으로 다운로드 후 삭제 |
| 10 | ② | ①은 PGP, ③은 MTA 설정, ④는 SPF |
| 11 | ② | none=보고만, quarantine=격리, reject=거부 |
| 12 | ② | ①은 존 전송 유출, ③은 터널링, ④는 증폭 |
| 13 | ① | 오픈 리졸버 제거가 핵심(+RRL, 위조 IP 필터링) |
| 14 | ② | Polyinstantiation, 추론 방지 목적 |
| 15 | ① | API 방식은 앱에서 암호화 → 소스 수정 필요, DB 독립적 |
| 16 | ② | 게이트웨이는 PI 원문(봉투), OIMD, DS. 상점은 OI, PIMD, DS |
| 17 | ① | WAP Gap |
| 18 | ③ | 코드오류 |
| 19 | ③ | Software Composition Analysis |
| 20 | ③ | 인벤토리(자산) 관리 실패 |